Exemplo n.º 1
0
SpeculatedType speculationFromValue(JSValue value)
{
    if (value.isEmpty())
        return SpecEmpty;
    if (value.isInt32())
        return SpecInt32;
    if (value.isDouble()) {
        double number = value.asNumber();
        if (number != number)
            return SpecDoubleNaN;
        if (value.isMachineInt())
            return SpecInt52AsDouble;
        return SpecNonIntAsDouble;
    }
    if (value.isCell())
        return speculationFromCell(value.asCell());
    if (value.isBoolean())
        return SpecBoolean;
    ASSERT(value.isUndefinedOrNull());
    return SpecOther;
}
Exemplo n.º 2
0
Arguments* StackVisitor::Frame::existingArguments()
{
    if (codeBlock()->codeType() != FunctionCode)
        return 0;
    if (!codeBlock()->usesArguments())
        return 0;
    
    VirtualRegister reg;
        
#if ENABLE(DFG_JIT)
    if (isInlinedFrame())
        reg = inlineCallFrame()->argumentsRegister;
    else
#endif // ENABLE(DFG_JIT)
        reg = codeBlock()->argumentsRegister();
    
    JSValue result = callFrame()->r(unmodifiedArgumentsRegister(reg).offset()).jsValue();
    if (!result || !result.isCell()) // Protect against Undefined in case we throw in op_enter.
        return 0;
    return jsCast<Arguments*>(result);
}
Exemplo n.º 3
0
void AbstractValue::set(Graph& graph, JSValue value)
{
    if (!!value && value.isCell()) {
        m_currentKnownStructure.makeTop();
        Structure* structure = value.asCell()->structure();
        setFuturePossibleStructure(graph, structure);
        m_arrayModes = asArrayModes(structure->indexingType());
        clobberArrayModes();
    } else {
        m_currentKnownStructure.clear();
        m_futurePossibleStructure.clear();
        m_arrayModes = 0;
    }
        
    m_type = speculationFromValue(value);
    if (m_type == SpecInt52AsDouble)
        m_type = SpecInt52;
    m_value = value;
        
    checkConsistency();
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
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));
}
Exemplo n.º 6
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 && isIndex(propertyAsUInt32))
                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);
                }
            }
        }
    }

    baseValue.requireObjectCoercible(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());
    auto propertyName = property.toPropertyKey(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());
    return JSValue::encode(baseValue.get(exec, propertyName));
}
Exemplo n.º 7
0
EncodedJSValue DFG_OPERATION 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()) {
            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));
    return JSValue::encode(baseValue.get(exec, ident));
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
    void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)
    {
        NodeOrigin origin = node->origin;
        Edge childEdge = node->child1();
        Node* child = childEdge.node();

        ASSERT(variant.oldStructure() == structure);
        
        bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
        
        // Now before we do anything else, push the CFA forward over the PutById
        // and make sure we signal to the loop that it should continue and not
        // do any eliminations.
        m_interpreter.execute(indexInBlock);

        if (needsWatchpoint) {
            m_insertionSet.insertNode(
                indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
                OpInfo(structure), childEdge);
        } else if (needsCellCheck) {
            m_insertionSet.insertNode(
                indexInBlock, SpecNone, Phantom, origin, childEdge);
        }

        childEdge.setUseKind(KnownCellUse);

        StructureTransitionData* transitionData = 0;
        if (variant.kind() == PutByIdVariant::Transition) {
            transitionData = m_graph.addStructureTransitionData(
                StructureTransitionData(structure, variant.newStructure()));

            if (node->op() == PutById) {
                if (!structure->storedPrototype().isNull()) {
                    addStructureTransitionCheck(
                        origin, indexInBlock,
                        structure->storedPrototype().asCell());
                }

                m_graph.chains().addLazily(variant.structureChain());

                for (unsigned i = 0; i < variant.structureChain()->size(); ++i) {
                    JSValue prototype = variant.structureChain()->at(i)->storedPrototype();
                    if (prototype.isNull())
                        continue;
                    ASSERT(prototype.isCell());
                    addStructureTransitionCheck(
                        origin, indexInBlock, prototype.asCell());
                }
            }
        }

        Edge propertyStorage;

        if (isInlineOffset(variant.offset()))
            propertyStorage = childEdge;
        else if (
            variant.kind() == PutByIdVariant::Replace
            || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) {
            propertyStorage = Edge(m_insertionSet.insertNode(
                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
        } else if (!structure->outOfLineCapacity()) {
            ASSERT(variant.newStructure()->outOfLineCapacity());
            ASSERT(!isInlineOffset(variant.offset()));
            Node* allocatePropertyStorage = m_insertionSet.insertNode(
                indexInBlock, SpecNone, AllocatePropertyStorage,
                origin, OpInfo(transitionData), childEdge);
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
            propertyStorage = Edge(allocatePropertyStorage);
        } else {
            ASSERT(structure->outOfLineCapacity());
            ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());
            ASSERT(!isInlineOffset(variant.offset()));

            Node* reallocatePropertyStorage = m_insertionSet.insertNode(
                indexInBlock, SpecNone, ReallocatePropertyStorage, origin,
                OpInfo(transitionData), childEdge,
                Edge(m_insertionSet.insertNode(
                    indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
            propertyStorage = Edge(reallocatePropertyStorage);
        }

        if (variant.kind() == PutByIdVariant::Transition) {
            Node* putStructure = m_graph.addNode(SpecNone, PutStructure, origin, OpInfo(transitionData), childEdge);
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
            m_insertionSet.insert(indexInBlock, putStructure);
        }

        node->convertToPutByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
        m_insertionSet.insertNode(
            indexInBlock, SpecNone, StoreBarrier, origin, 
            Edge(node->child2().node(), KnownCellUse));

        StorageAccessData storageAccessData;
        storageAccessData.offset = variant.offset();
        storageAccessData.identifierNumber = identifierNumber;
        m_graph.m_storageAccessData.append(storageAccessData);
    }
Exemplo n.º 10
0
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncIsTypedArrayView(ExecState* exec)
{
    JSValue value = exec->uncheckedArgument(0);
    return JSValue::encode(jsBoolean(value.isCell() && isTypedView(value.asCell()->classInfo()->typedArrayStorageType)));
}
    bool run()
    {
        ASSERT(m_graph.m_form == ThreadedCPS);
        
        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
            if (!variable->isRoot())
                continue;
            variable->clearVotes();
        }
        
        // Identify the set of variables that are always subject to the same structure
        // checks. For now, only consider monomorphic structure checks (one structure).
        
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
                Node* node = block->at(indexInBlock);
                switch (node->op()) {
                case CheckStructure:
                case StructureTransitionWatchpoint: {
                    Node* child = node->child1().node();
                    if (child->op() != GetLocal)
                        break;
                    VariableAccessData* variable = child->variableAccessData();
                    variable->vote(VoteStructureCheck);
                    if (!shouldConsiderForHoisting(variable))
                        break;
                    noticeStructureCheck(variable, node->structureSet());
                    break;
                }
                    
                case ForwardCheckStructure:
                case ForwardStructureTransitionWatchpoint:
                    // We currently rely on the fact that we're the only ones who would
                    // insert this node.
                    RELEASE_ASSERT_NOT_REACHED();
                    break;
                    
                case GetByOffset:
                case PutByOffset:
                case PutStructure:
                case AllocatePropertyStorage:
                case ReallocatePropertyStorage:
                case GetButterfly:
                case GetByVal:
                case PutByVal:
                case PutByValAlias:
                case GetArrayLength:
                case CheckArray:
                case GetIndexedPropertyStorage:
                case Phantom:
                    // Don't count these uses.
                    break;
                    
                case ArrayifyToStructure:
                case Arrayify:
                    if (node->arrayMode().conversion() == Array::RageConvert) {
                        // Rage conversion changes structures. We should avoid tying to do
                        // any kind of hoisting when rage conversion is in play.
                        Node* child = node->child1().node();
                        if (child->op() != GetLocal)
                            break;
                        VariableAccessData* variable = child->variableAccessData();
                        variable->vote(VoteOther);
                        if (!shouldConsiderForHoisting(variable))
                            break;
                        noticeStructureCheck(variable, 0);
                    }
                    break;
                    
                case SetLocal: {
                    // Find all uses of the source of the SetLocal. If any of them are a
                    // kind of CheckStructure, then we should notice them to ensure that
                    // we're not hoisting a check that would contravene checks that are
                    // already being performed.
                    VariableAccessData* variable = node->variableAccessData();
                    if (!shouldConsiderForHoisting(variable))
                        break;
                    Node* source = node->child1().node();
                    for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) {
                        Node* subNode = block->at(subIndexInBlock);
                        switch (subNode->op()) {
                        case CheckStructure: {
                            if (subNode->child1() != source)
                                break;
                            
                            noticeStructureCheck(variable, subNode->structureSet());
                            break;
                        }
                        case StructureTransitionWatchpoint: {
                            if (subNode->child1() != source)
                                break;
                            
                            noticeStructureCheck(variable, subNode->structure());
                            break;
                        }
                        default:
                            break;
                        }
                    }
                    
                    m_graph.voteChildren(node, VoteOther);
                    break;
                }
                case GarbageValue:
                    break;
                    
                default:
                    m_graph.voteChildren(node, VoteOther);
                    break;
                }
            }
        }
        
        // Disable structure hoisting on variables that appear to mostly be used in
        // contexts where it doesn't make sense.
        
        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
            if (!variable->isRoot())
                continue;
            if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting())
                continue;
            HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
            if (iter == m_map.end())
                continue;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
            dataLog(
                "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
                " because the ratio is ", variable->voteRatio(), ".\n");
#endif
            iter->value.m_structure = 0;
        }
        
        // Disable structure check hoisting for variables that cross the OSR entry that
        // we're currently taking, and where the value currently does not have the
        // structure we want.
        
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            ASSERT(block->isReachable);
            if (!block->isOSRTarget)
                continue;
            if (block->bytecodeBegin != m_graph.m_osrEntryBytecodeIndex)
                continue;
            for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) {
                int operand = m_graph.m_mustHandleValues.operandForIndex(i);
                Node* node = block->variablesAtHead.operand(operand);
                if (!node)
                    continue;
                VariableAccessData* variable = node->variableAccessData();
                HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
                if (iter == m_map.end())
                    continue;
                if (!iter->value.m_structure)
                    continue;
                JSValue value = m_graph.m_mustHandleValues[i];
                if (!value || !value.isCell()) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
                    dataLog(
                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
                        " because the OSR entry value is not a cell: ", value, ".\n");
#endif
                    iter->value.m_structure = 0;
                    continue;
                }
                if (value.asCell()->structure() != iter->value.m_structure) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
                    dataLog(
                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
                        " because the OSR entry value has structure ",
                        RawPointer(value.asCell()->structure()), " and we wanted ",
                        RawPointer(iter->value.m_structure), ".\n");
#endif
                    iter->value.m_structure = 0;
                    continue;
                }
            }
        }

        bool changed = false;

#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin();
            it != m_map.end(); ++it) {
            if (!it->value.m_structure) {
                dataLog(
                    "Not hoisting checks for ", VariableAccessDataDump(m_graph, it->key),
                    " because of heuristics.\n");
                continue;
            }
            dataLog("Hoisting checks for ", VariableAccessDataDump(m_graph, it->key), "\n");
        }
#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        
        // Place CheckStructure's at SetLocal sites.
        
        InsertionSet insertionSet(m_graph);
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
                Node* node = block->at(indexInBlock);
                // Be careful not to use 'node' after appending to the graph. In those switch
                // cases where we need to append, we first carefully extract everything we need
                // from the node, before doing any appending.
                switch (node->op()) {
                case SetArgument: {
                    ASSERT(!blockIndex);
                    // Insert a GetLocal and a CheckStructure immediately following this
                    // SetArgument, if the variable was a candidate for structure hoisting.
                    // If the basic block previously only had the SetArgument as its
                    // variable-at-tail, then replace it with this GetLocal.
                    VariableAccessData* variable = node->variableAccessData();
                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
                    if (iter == m_map.end())
                        break;
                    if (!iter->value.m_structure)
                        break;
                    
                    CodeOrigin codeOrigin = node->codeOrigin;
                    
                    Node* getLocal = insertionSet.insertNode(
                        indexInBlock + 1, variable->prediction(), GetLocal, codeOrigin,
                        OpInfo(variable), Edge(node));
                    insertionSet.insertNode(
                        indexInBlock + 1, SpecNone, CheckStructure, codeOrigin,
                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
                        Edge(getLocal, CellUse));

                    if (block->variablesAtTail.operand(variable->local()) == node)
                        block->variablesAtTail.operand(variable->local()) = getLocal;
                    
                    m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocal);
                    
                    changed = true;
                    break;
                }
                    
                case SetLocal: {
                    VariableAccessData* variable = node->variableAccessData();
                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
                    if (iter == m_map.end())
                        break;
                    if (!iter->value.m_structure)
                        break;

                    // First insert a dead SetLocal to tell OSR that the child's value should
                    // be dropped into this bytecode variable if the CheckStructure decides
                    // to exit.
                    
                    CodeOrigin codeOrigin = node->codeOrigin;
                    Edge child1 = node->child1();
                    
                    insertionSet.insertNode(
                        indexInBlock, SpecNone, SetLocal, codeOrigin, OpInfo(variable), child1);

                    // Use a ForwardCheckStructure to indicate that we should exit to the
                    // next bytecode instruction rather than reexecuting the current one.
                    insertionSet.insertNode(
                        indexInBlock, SpecNone, ForwardCheckStructure, codeOrigin,
                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
                        Edge(child1.node(), CellUse));
                    changed = true;
                    break;
                }
                    
                default:
                    break;
                }
            }
            insertionSet.execute(block);
        }
        
        return changed;
    }
Exemplo n.º 12
0
bool CallFrame::hasActivation() const
{
    JSValue activation = uncheckedActivation();
    return !!activation && activation.isCell();
}
Exemplo n.º 13
0
EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec)
{
    JSValue value = exec->uncheckedArgument(0);
    return JSValue::encode(jsBoolean(value.isCell() && value.asCell()->type() == JSMapType));
}
Exemplo n.º 14
0
    bool dumpIfTerminal(JSValue value)
    {
        if (!value.isCell()) {
            dumpImmediate(value);
            return true;
        }

        if (value.isString()) {
            UString str = asString(value)->value(m_exec);
            dumpString(str);
            return true;
        }

        if (value.isNumber()) {
            write(DoubleTag);
            write(value.asNumber());
            return true;
        }

        if (value.isObject() && asObject(value)->inherits(&DateInstance::s_info)) {
            write(DateTag);
            write(asDateInstance(value)->internalNumber());
            return true;
        }

        if (isArray(value))
            return false;
           
        // Object cannot be serialized because the act of walking the object creates new objects
        if (value.isObject() && asObject(value)->inherits(&JSNavigator::s_info)) {
            fail();
            write(NullTag);
            return true; 
        }

        if (value.isObject()) {
            JSObject* obj = asObject(value);
            if (obj->inherits(&JSFile::s_info)) {
                write(FileTag);
                write(toFile(obj));
                return true;
            }
            if (obj->inherits(&JSFileList::s_info)) {
                FileList* list = toFileList(obj);
                write(FileListTag);
                unsigned length = list->length();
                write(length);
                for (unsigned i = 0; i < length; i++)
                    write(list->item(i));
                return true;
            }
            if (obj->inherits(&JSBlob::s_info)) {
                write(BlobTag);
                Blob* blob = toBlob(obj);
                write(blob->url());
                write(blob->type());
                write(blob->size());
                return true;
            }
            if (obj->inherits(&JSImageData::s_info)) {
                ImageData* data = toImageData(obj);
                write(ImageDataTag);
                write(data->width());
                write(data->height());
                write(data->data()->length());
                write(data->data()->data()->data(), data->data()->length());
                return true;
            }
            if (obj->inherits(&RegExpObject::s_info)) {
                RegExpObject* regExp = asRegExpObject(obj);
                char flags[3];
                int flagCount = 0;
                if (regExp->regExp()->global())
                    flags[flagCount++] = 'g';
                if (regExp->regExp()->ignoreCase())
                    flags[flagCount++] = 'i';
                if (regExp->regExp()->multiline())
                    flags[flagCount++] = 'm';
                write(RegExpTag);
                write(regExp->regExp()->pattern());
                write(UString(flags, flagCount));
                return true;
            }
            if (obj->inherits(&JSMessagePort::s_info)) {
                ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
                if (index != m_transferredMessagePorts.end()) {
                    write(MessagePortReferenceTag);
                    uint32_t i = index->second;
                    write(i);
                    return true;
                }
                return false;
            }

            CallData unusedData;
            if (getCallData(value, unusedData) == CallTypeNone)
                return false;
        }
        // Any other types are expected to serialize as null.
        write(NullTag);
        return true;
    }
Exemplo n.º 15
0
void SlotVisitor::append(JSValue value)
{
    if (!value || !value.isCell())
        return;
    setMarkedAndAppendToMarkStack(value.asCell());
}