bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value) { AbstractValue oldMe = *this; if (isClear()) { FrozenValue* frozenValue = graph.freeze(value); if (frozenValue->pointsToHeap()) { m_structure = frozenValue->structure(); m_arrayModes = asArrayModes(frozenValue->structure()->indexingType()); } else { m_structure.clear(); m_arrayModes = 0; } m_type = speculationFromValue(value); m_value = value; } else { mergeSpeculation(m_type, speculationFromValue(value)); if (!!value && value.isCell()) { Structure* structure = value.asCell()->structure(); graph.registerStructure(structure); mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingType())); m_structure.merge(StructureSet(structure)); } if (m_value != value) m_value = JSValue(); } checkConsistency(); assertIsRegistered(graph); return oldMe != *this; }
void AbstractValue::observeTransitions(const TransitionVector& vector) { if (m_type & SpecCell) { m_structure.observeTransitions(vector); ArrayModes newModes = 0; for (unsigned i = vector.size(); i--;) { if (m_arrayModes & asArrayModes(vector[i].previous->indexingType())) newModes |= asArrayModes(vector[i].next->indexingType()); } m_arrayModes |= newModes; } checkConsistency(); }
ArrayModes StructureSet::arrayModesFromStructures() const { if (isThin()) { if (!singleStructure()) return 0; return asArrayModes(singleStructure()->indexingType()); } ArrayModes result = 0; OutOfLineList* list = structureList(); for (unsigned i = 0; i < list->m_length; ++i) mergeArrayModes(result, asArrayModes(list->list()[i]->indexingType())); return result; }
void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobberState clobberState) { if (!!value && value.value().isCell()) { Structure* structure = value.structure(); // FIXME: This check may not be necessary since any frozen value should have its structure // watched already. // https://bugs.webkit.org/show_bug.cgi?id=136055 if (graph.registerStructure(structure) == StructureRegisteredAndWatched) { m_structure = structure; if (clobberState == StructuresAreClobbered) { m_arrayModes = ALL_ARRAY_MODES; m_structure.clobber(); } else m_arrayModes = asArrayModes(structure->indexingType()); } else { m_structure.makeTop(); m_arrayModes = ALL_ARRAY_MODES; } } else { m_structure.clear(); m_arrayModes = 0; } m_type = speculationFromValue(value.value()); m_value = value.value(); checkConsistency(); assertIsRegistered(graph); }
void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobberState clobberState) { if (!!value && value.value().isCell()) { Structure* structure = value.structure(); if (graph.registerStructure(structure) == StructureRegisteredAndWatched) { m_structure = structure; if (clobberState == StructuresAreClobbered) { m_arrayModes = ALL_ARRAY_MODES; m_structure.clobber(); } else m_arrayModes = asArrayModes(structure->indexingType()); } else { m_structure.makeTop(); m_arrayModes = ALL_ARRAY_MODES; } } else { m_structure.clear(); m_arrayModes = 0; } m_type = speculationFromValue(value.value()); m_value = value.value(); checkConsistency(); assertIsRegistered(graph); }
ArrayModes RegisteredStructureSet::arrayModesFromStructures() const { ArrayModes result = 0; forEach( [&] (RegisteredStructure structure) { mergeArrayModes(result, asArrayModes(structure->indexingType())); }); return result; }
void AbstractValue::set(Graph& graph, Structure* structure) { m_currentKnownStructure = structure; setFuturePossibleStructure(graph, structure); m_arrayModes = asArrayModes(structure->indexingType()); m_type = speculationFromStructure(structure); m_value = JSValue(); checkConsistency(); }
void AbstractValue::set(Graph& graph, Structure* structure) { m_structure = structure; m_arrayModes = asArrayModes(structure->indexingType()); m_type = speculationFromStructure(structure); m_value = JSValue(); checkConsistency(); assertIsRegistered(graph); }
bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value, IndexingType shape) const { switch (arrayClass()) { case Array::OriginalArray: return value.m_currentKnownStructure.hasSingleton() && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray) && graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(value.m_currentKnownStructure.singleton()); case Array::Array: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray))) return true; return value.m_currentKnownStructure.hasSingleton() && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); default: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) return true; return value.m_currentKnownStructure.hasSingleton() && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; } }
void AbstractValue::setMostSpecific(Graph& graph, JSValue value) { if (!!value && value.isCell()) { Structure* structure = value.asCell()->structure(); m_currentKnownStructure = structure; setFuturePossibleStructure(graph, structure); m_arrayModes = asArrayModes(structure->indexingType()); } else { m_currentKnownStructure.clear(); m_futurePossibleStructure.clear(); m_arrayModes = 0; } m_type = speculationFromValue(value); m_value = value; checkConsistency(); }
void AbstractValue::setOSREntryValue(Graph& graph, const FrozenValue& value) { if (!!value && value.value().isCell()) { Structure* structure = value.structure(); graph.registerStructure(structure); m_structure = structure; m_arrayModes = asArrayModes(structure->indexingType()); } else { m_structure.clear(); m_arrayModes = 0; } m_type = speculationFromValue(value.value()); m_value = value.value(); checkConsistency(); assertIsRegistered(graph); }
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(); }
ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe) { Array::Class nonArray; if (profile->usesOriginalArrayStructures(locker)) nonArray = Array::OriginalNonArray; else nonArray = Array::NonArray; ArrayModes observed = profile->observedArrayModes(locker); switch (observed) { case 0: return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker)) return ArrayMode(Array::Undecided, nonArray, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::SelectUsingPredictions, nonArray).withSpeculationFromProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithUndecided): if (action == Array::Write) return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::Generic); case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided): if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker)) return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithInt32): return ArrayMode(Array::Int32, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithInt32): return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32): return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithDouble): return ArrayMode(Array::Double, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithDouble): return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble): return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithContiguous): return ArrayMode(Array::Contiguous, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); default: if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker)) return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe); Array::Type type; Array::Class arrayClass; if (shouldUseSlowPutArrayStorage(observed)) type = Array::SlowPutArrayStorage; else if (shouldUseFastArrayStorage(observed)) type = Array::ArrayStorage; else if (shouldUseContiguous(observed)) type = Array::Contiguous; else if (shouldUseDouble(observed)) type = Array::Double; else if (shouldUseInt32(observed)) type = Array::Int32; else type = Array::Undecided; if (hasSeenArray(observed) && hasSeenNonArray(observed)) arrayClass = Array::PossiblyArray; else if (hasSeenArray(observed)) arrayClass = Array::Array; else if (hasSeenNonArray(observed)) arrayClass = nonArray; else arrayClass = Array::PossiblyArray; return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe); } }
bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) const { switch (type()) { case Array::Generic: return true; case Array::ForceExit: return false; case Array::String: return speculationChecked(value.m_type, SpecString); case Array::Int32: return alreadyChecked(graph, node, value, Int32Shape); case Array::Double: return alreadyChecked(graph, node, value, DoubleShape); case Array::Contiguous: return alreadyChecked(graph, node, value, ContiguousShape); case Array::ArrayStorage: return alreadyChecked(graph, node, value, ArrayStorageShape); case Array::SlowPutArrayStorage: switch (arrayClass()) { case Array::OriginalArray: CRASH(); return false; case Array::Array: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) return true; return value.m_currentKnownStructure.hasSingleton() && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); default: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) return true; return value.m_currentKnownStructure.hasSingleton() && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); } case Array::Arguments: return speculationChecked(value.m_type, SpecArguments); case Array::Int8Array: return speculationChecked(value.m_type, SpecInt8Array); case Array::Int16Array: return speculationChecked(value.m_type, SpecInt16Array); case Array::Int32Array: return speculationChecked(value.m_type, SpecInt32Array); case Array::Uint8Array: return speculationChecked(value.m_type, SpecUint8Array); case Array::Uint8ClampedArray: return speculationChecked(value.m_type, SpecUint8ClampedArray); case Array::Uint16Array: return speculationChecked(value.m_type, SpecUint16Array); case Array::Uint32Array: return speculationChecked(value.m_type, SpecUint32Array); case Array::Float32Array: return speculationChecked(value.m_type, SpecFloat32Array); case Array::Float64Array: return speculationChecked(value.m_type, SpecFloat64Array); case Array::SelectUsingPredictions: case Array::Unprofiled: case Array::Undecided: break; } CRASH(); return false; }
ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe) { ArrayModes observed = profile->observedArrayModes(); switch (observed) { case 0: return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) return ArrayMode(Array::Undecided, Array::NonArray, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(ArrayWithUndecided): if (action == Array::Write) return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::Generic); case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(NonArrayWithInt32): return ArrayMode(Array::Int32, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithInt32): return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32): return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithDouble): return ArrayMode(Array::Double, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithDouble): return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble): return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); default: if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses()) return ArrayMode(Array::SelectUsingPredictions); Array::Type type; Array::Class arrayClass; if (shouldUseSlowPutArrayStorage(observed)) type = Array::SlowPutArrayStorage; else if (shouldUseFastArrayStorage(observed)) type = Array::ArrayStorage; else if (shouldUseContiguous(observed)) type = Array::Contiguous; else if (shouldUseDouble(observed)) type = Array::Double; else if (shouldUseInt32(observed)) type = Array::Int32; else type = Array::Undecided; if (observed & (asArrayModes(ArrayWithUndecided) | asArrayModes(ArrayWithInt32) | asArrayModes(ArrayWithDouble) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) arrayClass = Array::Array; else if (observed & (asArrayModes(NonArray) | asArrayModes(NonArrayWithInt32) | asArrayModes(NonArrayWithDouble) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage))) arrayClass = Array::NonArray; else arrayClass = Array::PossiblyArray; return ArrayMode(type, arrayClass, Array::Convert).withProfile(profile, makeSafe); } }
void dumpArrayModes(PrintStream& out, ArrayModes arrayModes) { if (!arrayModes) { out.print("<empty>"); return; } if (arrayModes == ALL_ARRAY_MODES) { out.print("TOP"); return; } CommaPrinter comma("|"); if (arrayModes & asArrayModes(NonArray)) out.print(comma, "NonArray"); if (arrayModes & asArrayModes(NonArrayWithInt32)) out.print(comma, "NonArrayWithInt32"); if (arrayModes & asArrayModes(NonArrayWithDouble)) out.print(comma, "NonArrayWithDouble"); if (arrayModes & asArrayModes(NonArrayWithContiguous)) out.print(comma, "NonArrayWithContiguous"); if (arrayModes & asArrayModes(NonArrayWithArrayStorage)) out.print(comma, "NonArrayWithArrayStorage"); if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage)) out.print(comma, "NonArrayWithSlowPutArrayStorage"); if (arrayModes & asArrayModes(ArrayClass)) out.print(comma, "ArrayClass"); if (arrayModes & asArrayModes(ArrayWithUndecided)) out.print(comma, "ArrayWithUndecided"); if (arrayModes & asArrayModes(ArrayWithInt32)) out.print(comma, "ArrayWithInt32"); if (arrayModes & asArrayModes(ArrayWithDouble)) out.print(comma, "ArrayWithDouble"); if (arrayModes & asArrayModes(ArrayWithContiguous)) out.print(comma, "ArrayWithContiguous"); if (arrayModes & asArrayModes(ArrayWithArrayStorage)) out.print(comma, "ArrayWithArrayStorage"); if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage)) out.print(comma, "ArrayWithSlowPutArrayStorage"); }