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; } } }
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)); }
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); }
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(); }
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; }
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 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 }
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; }
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; }
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; }