void ObjectInitializationScope::verifyPropertiesAreInitialized(JSObject* object) { Butterfly* butterfly = object->butterfly(); Structure* structure = object->structure(m_vm); IndexingType indexingType = structure->indexingType(); unsigned vectorLength = butterfly->vectorLength(); if (UNLIKELY(hasUndecided(indexingType)) || !hasIndexedProperties(indexingType)) { // Nothing to verify. } else if (LIKELY(!hasAnyArrayStorage(indexingType))) { auto data = butterfly->contiguous().data(); for (unsigned i = 0; i < vectorLength; ++i) { if (isScribbledValue(data[i].get())) { dataLogLn("Found scribbled value at i = ", i); ASSERT_NOT_REACHED(); } } } else { ArrayStorage* storage = butterfly->arrayStorage(); for (unsigned i = 0; i < vectorLength; ++i) { if (isScribbledValue(storage->m_vector[i].get())) { dataLogLn("Found scribbled value at i = ", i); ASSERT_NOT_REACHED(); } } } auto isSafeEmptyValueForGCScanning = [] (JSValue value) { #if USE(JSVALUE64) return !value; #else return !value || !JSValue::encode(value); #endif }; for (int64_t i = 0; i < static_cast<int64_t>(structure->outOfLineCapacity()); i++) { // We rely on properties past the last offset be zero for concurrent GC. if (i + firstOutOfLineOffset > structure->lastOffset()) ASSERT(isSafeEmptyValueForGCScanning(butterfly->propertyStorage()[-i - 1].get())); else if (isScribbledValue(butterfly->propertyStorage()[-i - 1].get())) { dataLogLn("Found scribbled property at i = ", -i - 1); ASSERT_NOT_REACHED(); } } }
void handle() { switch (m_node->op()) { case CompareEqConstant: case IsUndefined: handleMasqueradesAsUndefined(); break; case CompareEq: if (m_node->isBinaryUseKind(ObjectUse) || (m_node->child1().useKind() == ObjectUse && m_node->child2().useKind() == ObjectOrOtherUse) || (m_node->child1().useKind() == ObjectOrOtherUse && m_node->child2().useKind() == ObjectUse)) handleMasqueradesAsUndefined(); break; case LogicalNot: case Branch: if (m_node->child1().useKind() == ObjectOrOtherUse) handleMasqueradesAsUndefined(); break; case GetByVal: if (m_node->arrayMode().type() == Array::Double && m_node->arrayMode().isSaneChain()) { addLazily(globalObject()->arrayPrototype()->structure()->transitionWatchpointSet()); addLazily(globalObject()->objectPrototype()->structure()->transitionWatchpointSet()); } if (m_node->arrayMode().type() == Array::String) handleStringGetByVal(); if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) addLazily(view); break; case PutByVal: if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) addLazily(view); break; case StringCharAt: handleStringGetByVal(); break; case NewArray: case NewArrayWithSize: case NewArrayBuffer: if (!globalObject()->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) addLazily(globalObject()->havingABadTimeWatchpoint()); break; case AllocationProfileWatchpoint: addLazily(m_node->castOperand<JSFunction*>()->allocationProfileWatchpointSet()); break; case VarInjectionWatchpoint: addLazily(globalObject()->varInjectionWatchpoint()); break; case TypedArrayWatchpoint: addLazily(m_node->typedArray()); break; default: break; } }