Esempio n. 1
0
EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
{
    VM& vm = exec->vm();
    NativeCallFrameTracer tracer(&vm, exec);
    
    JSValue baseValue = JSValue::decode(encodedBase);
    JSValue property = JSValue::decode(encodedProperty);

    if (LIKELY(baseValue.isCell())) {
        JSCell* base = baseValue.asCell();

        if (property.isUInt32()) {
            return getByVal(exec, base, property.asUInt32());
        } else if (property.isDouble()) {
            double propertyAsDouble = property.asDouble();
            uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
            if (propertyAsUInt32 == propertyAsDouble)
                return getByVal(exec, base, propertyAsUInt32);
        } else if (property.isString()) {
            Structure& structure = *base->structure(vm);
            if (JSCell::canUseFastGetOwnProperty(structure)) {
                if (AtomicStringImpl* existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
                    if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString))
                        return JSValue::encode(result);
                }
            }
        }
    }

    PropertyName propertyName = property.toPropertyKey(exec);
    return JSValue::encode(baseValue.get(exec, propertyName));
}
Esempio n. 2
0
void JSGlobalData::storeVPtrs()
{
    // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
    // COMPILE_ASSERTS below check that this is true.
    char storage[64];

    COMPILE_ASSERT(sizeof(JSFinalObject) <= sizeof(storage), sizeof_JSFinalObject_must_be_less_than_storage);
    JSCell* jsFinalObject = new (storage) JSFinalObject(JSFinalObject::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsFinalObjectVPtr = jsFinalObject->vptr();

    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
    JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsArrayVPtr = jsArray->vptr();

    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();

    COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsStringVPtr = jsString->vptr();

    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
    JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
}
Esempio n. 3
0
EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
{
    JSGlobalData* globalData = &exec->globalData();
    NativeCallFrameTracer tracer(globalData, exec);
    
    JSValue baseValue = JSValue::decode(encodedBase);
    JSValue property = JSValue::decode(encodedProperty);

    if (LIKELY(baseValue.isCell())) {
        JSCell* base = baseValue.asCell();

        if (property.isUInt32()) {
            return getByVal(exec, base, property.asUInt32());
        } else if (property.isDouble()) {
            double propertyAsDouble = property.asDouble();
            uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
            if (propertyAsUInt32 == propertyAsDouble)
                return getByVal(exec, base, propertyAsUInt32);
        } else if (property.isString()) {
            if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
                return JSValue::encode(result);
        }
    }

    Identifier ident(exec, property.toString(exec)->value(exec));
    return JSValue::encode(baseValue.get(exec, ident));
}
Esempio n. 4
0
MarkedBlock::FreeList MarkedBlock::specializedSweep()
{
    ASSERT(blockState != Allocated && blockState != FreeListed);
    ASSERT(destructorCallNeeded || sweepMode != SweepOnly);

    // This produces a free list that is ordered in reverse through the block.
    // This is fine, since the allocation code makes no assumptions about the
    // order of the free list.
    FreeCell* head = 0;
    size_t count = 0;
    for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
        if (blockState == Marked && m_marks.get(i))
            continue;

        JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
        if (blockState == Zapped && !cell->isZapped())
            continue;

        if (destructorCallNeeded && blockState != New)
            callDestructor(cell);

        if (sweepMode == SweepToFreeList) {
            FreeCell* freeCell = reinterpret_cast<FreeCell*>(cell);
            freeCell->next = head;
            head = freeCell;
            ++count;
        }
    }

    m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Zapped);
    return FreeList(head, count * cellSize());
}
Esempio n. 5
0
void JSGlobalData::releaseExecutableMemory()
{
    if (dynamicGlobalObject) {
        StackPreservingRecompiler recompiler;
        HashSet<JSCell*> roots;
        heap.getConservativeRegisterRoots(roots);
        HashSet<JSCell*>::iterator end = roots.end();
        for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
            ScriptExecutable* executable = 0;
            JSCell* cell = *ptr;
            if (cell->inherits(&ScriptExecutable::s_info))
                executable = static_cast<ScriptExecutable*>(*ptr);
            else if (cell->inherits(&JSFunction::s_info)) {
                JSFunction* function = jsCast<JSFunction*>(*ptr);
                if (function->isHostFunction())
                    continue;
                executable = function->jsExecutable();
            } else
                continue;
            ASSERT(executable->inherits(&ScriptExecutable::s_info));
            executable->unlinkCalls();
            if (executable->inherits(&FunctionExecutable::s_info))
                recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
                
        }
        heap.objectSpace().forEachCell<StackPreservingRecompiler>(recompiler);
    }
    m_regExpCache->invalidateCode();
    heap.collectAllGarbage();
}
Esempio n. 6
0
void SlotVisitor::appendJSCellOrAuxiliary(HeapCell* heapCell)
{
    if (!heapCell)
        return;
    
    ASSERT(!m_isCheckingForDefaultMarkViolation);
    
    if (Heap::testAndSetMarked(m_markingVersion, heapCell))
        return;
    
    switch (heapCell->cellKind()) {
    case HeapCell::JSCell: {
        JSCell* jsCell = static_cast<JSCell*>(heapCell);
        
        if (!jsCell->structure()) {
            ASSERT_NOT_REACHED();
            return;
        }
        
        jsCell->setCellState(CellState::Grey);

        appendToMarkStack(jsCell);
        return;
    }
        
    case HeapCell::Auxiliary: {
        noteLiveAuxiliaryCell(heapCell);
        return;
    } }
}
Esempio n. 7
0
void VM::releaseExecutableMemory()
{
    prepareToDiscardCode();

    if (entryScope) {
        StackPreservingRecompiler recompiler;
        HeapIterationScope iterationScope(heap);
        HashSet<JSCell*> roots;
        heap.getConservativeRegisterRoots(roots);
        HashSet<JSCell*>::iterator end = roots.end();
        for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
            ScriptExecutable* executable = 0;
            JSCell* cell = *ptr;
            if (cell->inherits(ScriptExecutable::info()))
                executable = static_cast<ScriptExecutable*>(*ptr);
            else if (cell->inherits(JSFunction::info())) {
                JSFunction* function = jsCast<JSFunction*>(*ptr);
                if (function->isHostFunction())
                    continue;
                executable = function->jsExecutable();
            } else
                continue;
            ASSERT(executable->inherits(ScriptExecutable::info()));
            executable->unlinkCalls();
            if (executable->inherits(FunctionExecutable::info()))
                recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));

        }
        heap.objectSpace().forEachLiveCell<StackPreservingRecompiler>(iterationScope, recompiler);
    }
    m_regExpCache->invalidateCode();
    heap.collectAllGarbage();
}
void InspectorHeapAgent::getRemoteObject(ErrorString& errorString, int heapObjectId, const String* optionalObjectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
{
    // Prevent the cell from getting collected as we look it up.
    VM& vm = m_environment.vm();
    JSLockHolder lock(vm);
    DeferGC deferGC(vm.heap);

    unsigned heapObjectIdentifier = static_cast<unsigned>(heapObjectId);
    const Optional<HeapSnapshotNode> optionalNode = nodeForHeapObjectIdentifier(errorString, heapObjectIdentifier);
    if (!optionalNode)
        return;

    JSCell* cell = optionalNode->cell;
    Structure* structure = cell->structure(m_environment.vm());
    if (!structure) {
        errorString = ASCIILiteral("Unable to get object details");
        return;
    }

    JSGlobalObject* globalObject = structure->globalObject();
    if (!globalObject) {
        errorString = ASCIILiteral("Unable to get object details");
        return;
    }

    InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(globalObject->globalExec());
    if (injectedScript.hasNoValue()) {
        errorString = ASCIILiteral("Unable to get object details - InjectedScript");
        return;
    }

    Deprecated::ScriptValue cellScriptValue(m_environment.vm(), JSValue(cell));
    String objectGroup = optionalObjectGroup ? *optionalObjectGroup : String();
    result = injectedScript.wrapObject(cellScriptValue, objectGroup, true);
}
Esempio n. 9
0
bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
{
    if (!object)
        return false;
    CallData callData;
    JSCell* cell = toJS(object);
    return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
}
std::unique_ptr<PolyProtoAccessChain> PolyProtoAccessChain::create(JSGlobalObject* globalObject, JSCell* base, JSObject* target, bool& usesPolyProto)
{
    JSCell* current = base;
    VM& vm = *base->vm();

    bool found = false;

    usesPolyProto = false;

    std::unique_ptr<PolyProtoAccessChain> result(new PolyProtoAccessChain());

    for (unsigned iterationNumber = 0; true; ++iterationNumber) {
        Structure* structure = current->structure(vm);

        if (!structure->propertyAccessesAreCacheable())
            return nullptr;

        if (structure->isProxy())
            return nullptr;

        if (structure->isDictionary()) {
            ASSERT(structure->isObject());
            if (structure->hasBeenFlattenedBefore())
                return nullptr;

            structure->flattenDictionaryStructure(vm, asObject(current));
        }

        // To save memory, we don't include the base in the chain. We let
        // AccessCase provide the base to us as needed.
        if (iterationNumber)
            result->m_chain.append(structure);
        else
            RELEASE_ASSERT(current == base);

        if (current == target) {
            found = true;
            break;
        }

        // We only have poly proto if we need to access our prototype via
        // the poly proto protocol. If the slot base is the only poly proto
        // thing in the chain, and we have a cache hit on it, then we're not
        // poly proto.
        usesPolyProto |= structure->hasPolyProto();

        JSValue prototype = structure->prototypeForLookup(globalObject, current);
        if (prototype.isNull())
            break;
        current = asObject(prototype);
    }

    if (!found && !!target)
        return nullptr;

    return result;
}
Esempio n. 11
0
bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
{
    if (!object)
        return false;
    JSLockHolder locker(toJS(ctx));
    CallData callData;
    JSCell* cell = toJS(object);
    return cell->methodTable()->getCallData(cell, callData) != CallType::None;
}
Esempio n. 12
0
void SamplingProfiler::processUnverifiedStackTraces()
{
    // This function needs to be called from the JSC execution thread.
    RELEASE_ASSERT(m_lock.isLocked());

    TinyBloomFilter filter = m_vm.heap.objectSpace().blocks().filter();
    MarkedBlockSet& markedBlockSet = m_vm.heap.objectSpace().blocks();

    for (unsigned i = m_indexOfNextStackTraceToVerify; i < m_stackTraces.size(); i++) {
        StackTrace& stackTrace = m_stackTraces[i]; 
        if (!stackTrace.needsVerification)
            continue;
        stackTrace.needsVerification = false;

        for (StackFrame& stackFrame : stackTrace.frames) {
            if (stackFrame.frameType != FrameType::UnverifiedCallee) {
                RELEASE_ASSERT(stackFrame.frameType == FrameType::VerifiedExecutable);
                continue;
            }

            JSValue callee = JSValue::decode(stackFrame.u.unverifiedCallee);
            if (!Heap::isValueGCObject(filter, markedBlockSet, callee)) {
                stackFrame.frameType = FrameType::Unknown;
                continue;
            }

            JSCell* calleeCell = callee.asCell();
            auto frameTypeFromCallData = [&] () -> FrameType {
                FrameType result = FrameType::Unknown;
                CallData callData;
                CallType callType;
                callType = getCallData(calleeCell, callData);
                if (callType == CallTypeHost)
                    result = FrameType::Host;

                return result;
            };

            if (calleeCell->type() != JSFunctionType) {
                stackFrame.frameType = frameTypeFromCallData();
                continue;
            }
            ExecutableBase* executable = static_cast<JSFunction*>(calleeCell)->executable();
            if (!executable) {
                stackFrame.frameType = frameTypeFromCallData();
                continue;
            }

            RELEASE_ASSERT(Heap::isPointerGCObject(filter, markedBlockSet, executable));
            stackFrame.frameType = FrameType::VerifiedExecutable;
            stackFrame.u.verifiedExecutable = executable;
            m_seenExecutables.add(executable);
        }
    }

    m_indexOfNextStackTraceToVerify = m_stackTraces.size();
}
Esempio n. 13
0
bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
{
    if (!object)
        return false;
    ExecState* exec = toJS(ctx);
    VM& vm = exec->vm();
    JSLockHolder locker(vm);
    CallData callData;
    JSCell* cell = toJS(object);
    return cell->methodTable(vm)->getCallData(cell, callData) != CallType::None;
}
void JSGlobalData::storeVPtrs()
{
    CollectorCell cell;
    void* storage = &cell;

    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
    JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
    JSGlobalData::jsArrayVPtr = jsArray->vptr();
    jsArray->~JSCell();

    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
    jsByteArray->~JSCell();

    COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    JSGlobalData::jsStringVPtr = jsString->vptr();
    jsString->~JSCell();

    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
    jsFunction->~JSCell();
}
void InspectorHeapAgent::getPreview(ErrorString& errorString, int heapObjectId, Inspector::Protocol::OptOutput<String>* resultString, RefPtr<Inspector::Protocol::Debugger::FunctionDetails>& functionDetails, RefPtr<Inspector::Protocol::Runtime::ObjectPreview>& objectPreview)
{
    // Prevent the cell from getting collected as we look it up.
    VM& vm = m_environment.vm();
    JSLockHolder lock(vm);
    DeferGC deferGC(vm.heap);

    unsigned heapObjectIdentifier = static_cast<unsigned>(heapObjectId);
    const Optional<HeapSnapshotNode> optionalNode = nodeForHeapObjectIdentifier(errorString, heapObjectIdentifier);
    if (!optionalNode)
        return;

    // String preview.
    JSCell* cell = optionalNode->cell;
    if (cell->isString()) {
        *resultString = cell->getString(nullptr);
        return;
    }

    // FIXME: Provide preview information for Internal Objects? CodeBlock, Executable, etc.

    Structure* structure = cell->structure(m_environment.vm());
    if (!structure) {
        errorString = ASCIILiteral("Unable to get object details - Structure");
        return;
    }

    JSGlobalObject* globalObject = structure->globalObject();
    if (!globalObject) {
        errorString = ASCIILiteral("Unable to get object details - GlobalObject");
        return;
    }

    InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(globalObject->globalExec());
    if (injectedScript.hasNoValue()) {
        errorString = ASCIILiteral("Unable to get object details - InjectedScript");
        return;
    }

    // Function preview.
    if (cell->inherits(JSFunction::info())) {
        Deprecated::ScriptValue functionScriptValue(m_environment.vm(), JSValue(cell));
        injectedScript.functionDetails(errorString, functionScriptValue, &functionDetails);
        return;
    }

    // Object preview.
    Deprecated::ScriptValue cellScriptValue(m_environment.vm(), JSValue(cell));
    objectPreview = injectedScript.previewValue(cellScriptValue);
}
void JSGlobalData::storeVPtrs()
{
    // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
    // COMPILE_ASSERTS below check that this is true.
    char storage[64];

    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
    JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
    JSGlobalData::jsArrayVPtr = jsArray->vptr();
    jsArray->~JSCell();

    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
    jsByteArray->~JSCell();

    COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    JSGlobalData::jsStringVPtr = jsString->vptr();
    jsString->~JSCell();

    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
    char executableStorage[sizeof(VPtrHackExecutable)];
    RefPtr<Structure> executableStructure = Structure::create(Structure::VPtrStealingHack, 0);
    JSCell* executable = new (executableStorage) VPtrHackExecutable(executableStructure.get());
    JSCell* jsFunction = new (storage) JSFunction(Structure::create(Structure::VPtrStealingHack, &JSFunction::s_info), static_cast<VPtrHackExecutable*>(executable));
    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
    executable->~JSCell();
    jsFunction->~JSCell();
}
Esempio n. 17
0
void JSGlobalData::storeVPtrs()
{
    // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
    // COMPILE_ASSERTS below check that this is true.
	
	// -----------Instrumentation----------- //
    char storage[128]; // changed from 64 to fit JSLabel
	// ------------------------------------- //

    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
    JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsArrayVPtr = jsArray->vptr();

    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();

    COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsStringVPtr = jsString->vptr();

    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
    JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
    CLOBBER_MEMORY();
    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
}
Esempio n. 18
0
void MarkStack::drain()
{
#if !ASSERT_DISABLED
    ASSERT(!m_isDraining);
    m_isDraining = true;
#endif
    while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
        while (!m_markSets.isEmpty() && m_values.size() < 50) {
            ASSERT(!m_markSets.isEmpty());
            MarkSet& current = m_markSets.last();
            ASSERT(current.m_values);
            JSValue* end = current.m_end;
            ASSERT(current.m_values);
            ASSERT(current.m_values != end);
        findNextUnmarkedNullValue:
            ASSERT(current.m_values != end);
            JSValue value = *current.m_values;
            current.m_values++;

            JSCell* cell;
            if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
                if (current.m_values == end) {
                    m_markSets.removeLast();
                    continue;
                }
                goto findNextUnmarkedNullValue;
            }

            if (cell->structure()->typeInfo().type() < CompoundType) {
                cell->JSCell::visitChildren(*this);
                if (current.m_values == end) {
                    m_markSets.removeLast();
                    continue;
                }
                goto findNextUnmarkedNullValue;
            }

            if (current.m_values == end)
                m_markSets.removeLast();

            visitChildren(cell);
        }
        while (!m_values.isEmpty())
            visitChildren(m_values.removeLast());
    }
#if !ASSERT_DISABLED
    m_isDraining = false;
#endif
}
Esempio n. 19
0
bool HandleHeap::isValidWeakNode(Node* node)
{
    if (!isLiveNode(node))
        return false;
    if (!node->isWeak())
        return false;

    JSValue value = *node->slot();
    if (!value || !value.isCell())
        return false;

    JSCell* cell = value.asCell();
    if (!cell || !cell->structure())
        return false;

    return true;
}
Esempio n. 20
0
void MarkStack::validateValue(JSValue value)
{
    if (!value)
        CRASH();
    if (!value.isCell())
        return;
    JSCell* cell = value.asCell();
    if (!cell)
        CRASH();

    if (!cell->structure())
        CRASH();

    // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
    // I hate this sentence.
    if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
        CRASH();
}
Esempio n. 21
0
bool HandleHeap::isValidWeakNode(Node* node)
{
    if (!node->isWeak())
        return false;

    JSValue value = *node->slot();
    if (!value || !value.isCell())
        return false;

    JSCell* cell = value.asCell();
    if (!cell || !cell->structure())
        return false;

#if ENABLE(JSC_ZOMBIES)
    if (cell->isZombie())
        return false;
#endif

    return true;
}
void DOMGCOutputConstraint::executeImpl(SlotVisitor& visitor)
{
    Heap& heap = m_vm.heap;
    
    if (heap.mutatorExecutionVersion() == m_lastExecutionVersion)
        return;
    
    m_lastExecutionVersion = heap.mutatorExecutionVersion();
    
    m_clientData.forEachOutputConstraintSpace(
        [&] (Subspace& subspace) {
            auto func = [] (SlotVisitor& visitor, HeapCell* heapCell, HeapCell::Kind) {
                SetRootMarkReasonScope rootScope(visitor, SlotVisitor::RootMarkReason::DOMGCOutput);
                JSCell* cell = static_cast<JSCell*>(heapCell);
                cell->methodTable(visitor.vm())->visitOutputConstraints(cell, visitor);
            };
            
            visitor.addParallelConstraintTask(subspace.forEachMarkedCellInParallel(func));
        });
}
Esempio n. 23
0
ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
{
    // This internalAppend is only intended for visits to object and array backing stores.
    // as it can change the JSValue pointed to be the argument when the original JSValue
    // is a string that contains the same contents as another string.

    StackStats::probe();
    ASSERT(slot);
    JSValue value = *slot;
    ASSERT(value);
    if (!value.isCell())
        return;

    JSCell* cell = value.asCell();
    if (!cell)
        return;

    validate(cell);

    if (m_shouldHashCons && cell->isString()) {
        JSString* string = jsCast<JSString*>(cell);
        if (string->shouldTryHashCons() && string->tryHashConsLock()) {
            UniqueStringMap::AddResult addResult = m_uniqueStrings.add(string->string().impl(), value);
            if (addResult.isNewEntry)
                string->setHashConsSingleton();
            else {
                JSValue existingJSValue = addResult.iterator->value;
                if (value != existingJSValue)
                    jsCast<JSString*>(existingJSValue.asCell())->clearHashConsSingleton();
                *slot = existingJSValue;
                string->releaseHashConsLock();
                return;
            }
            string->releaseHashConsLock();
        }
    }

    internalAppend(cell);
}
Esempio n. 24
0
EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
{
    JSValue baseValue = JSValue::decode(encodedBase);
    JSValue property = JSValue::decode(encodedProperty);

    if (LIKELY(baseValue.isCell())) {
        JSCell* base = baseValue.asCell();

        if (property.isUInt32()) {
            JSGlobalData* globalData = &exec->globalData();
            uint32_t i = property.asUInt32();

            // FIXME: the JIT used to handle these in compiled code!
            if (isJSArray(globalData, base) && asArray(base)->canGetIndex(i))
                return JSValue::encode(asArray(base)->getIndex(i));

            // FIXME: the JITstub used to relink this to an optimized form!
            if (isJSString(globalData, base) && asString(base)->canGetIndex(i))
                return JSValue::encode(asString(base)->getIndex(exec, i));

            // FIXME: the JITstub used to relink this to an optimized form!
            if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(i))
                return JSValue::encode(asByteArray(base)->getIndex(exec, i));

            return JSValue::encode(baseValue.get(exec, i));
        }

        if (property.isString()) {
            Identifier propertyName(exec, asString(property)->value(exec));
            PropertySlot slot(base);
            if (base->fastGetOwnPropertySlot(exec, propertyName, slot))
                return JSValue::encode(slot.getValue(exec, propertyName));
        }
    }

    Identifier ident(exec, property.toString(exec));
    return JSValue::encode(baseValue.get(exec, ident));
}
Esempio n. 25
0
VPtrSet::VPtrSet()
{
    // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
    void* storage = fastMalloc(sizeof(CollectorBlock));

    JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
    jsArrayVPtr = jsArray->vptr();
    jsArray->~JSCell();

    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    jsByteArrayVPtr = jsByteArray->vptr();
    jsByteArray->~JSCell();

    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    jsStringVPtr = jsString->vptr();
    jsString->~JSCell();

    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
    jsFunctionVPtr = jsFunction->vptr();
    jsFunction->~JSCell();

    fastFree(storage);
}
Esempio n. 26
0
InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
{
    if (value.isBoolean())
        return Boolean;
    if (value.isUndefinedOrNull())
        return Other;
    if (value.isInt32())
        return Int32;
    if (value.isNumber())
        return Number;
    if (value.isCell()) {
        JSCell* cell = value.asCell();
        if (cell->isString())
            return String;
        if (cell->isSymbol())
            return Symbol;
        if (cell->isObject()) {
            if (cell->structure()->transitionWatchpointSetIsStillValid())
                return Descriptor(ObjectWithStructure, cell->structure());
            return Object;
        }
    }
    return Top;
}