Revert "[builtins] Separate species protectors for Array, TypedArray, Promise"
This reverts commit 5728b3fbc5
.
Reason for revert: Breaks noi18n build
Original change's description:
> [builtins] Separate species protectors for Array, TypedArray, Promise
>
> Previously, there was one species protector for Array, TypedArray and
> Promise. This CL splits the protector in three separate ones. This means
> that invalidating one of them does not have negative performance
> implications for the other ones.
>
> Bug: chromium:835347, v8:7340
> Change-Id: Id84aa0071f17096192965264eb60ddadd1e8e73f
> Reviewed-on: https://chromium-review.googlesource.com/1023408
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#52733}
TBR=sigurds@chromium.org,bmeurer@chromium.org
Change-Id: Ied8b436e7991c759eb3b98702c142aa127a7e63c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:835347, v8:7340
Reviewed-on: https://chromium-review.googlesource.com/1024151
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52736}
This commit is contained in:
parent
be88e1c6a7
commit
75e282342c
@ -20,7 +20,7 @@ module array {
|
||||
let map: Map = a.map;
|
||||
if (!IsPrototypeInitialArrayPrototype(context, map)) goto Bailout;
|
||||
if (IsNoElementsProtectorCellInvalid()) goto Bailout;
|
||||
if (IsArraySpeciesProtectorCellInvalid()) goto Bailout;
|
||||
if (IsSpeciesProtectorCellInvalid()) goto Bailout;
|
||||
|
||||
// Fast path only works on fast elements kind and with writable length.
|
||||
let elementsKind: int32 = EnsureArrayPushable(map) otherwise Bailout;
|
||||
|
@ -199,9 +199,7 @@ extern macro BranchIfNotFastJSArray(Object, Context): never labels True, False;
|
||||
|
||||
extern macro IsPrototypeInitialArrayPrototype(Context, Map): bit;
|
||||
extern macro IsNoElementsProtectorCellInvalid(): bit;
|
||||
extern macro IsArraySpeciesProtectorCellInvalid(): bit;
|
||||
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bit;
|
||||
extern macro IsPromiseSpeciesProtectorCellInvalid(): bit;
|
||||
extern macro IsSpeciesProtectorCellInvalid(): bit;
|
||||
|
||||
extern operator '.elements_kind' macro LoadMapElementsKind(Map): int32;
|
||||
|
||||
|
@ -817,7 +817,7 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
||||
GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
|
||||
&runtime);
|
||||
|
||||
Node* species_protector = ArraySpeciesProtectorConstant();
|
||||
Node* species_protector = SpeciesProtectorConstant();
|
||||
Node* value =
|
||||
LoadObjectField(species_protector, PropertyCell::kValueOffset);
|
||||
TNode<Smi> const protector_invalid =
|
||||
@ -862,7 +862,7 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
||||
GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
|
||||
&runtime);
|
||||
|
||||
Node* species_protector = ArraySpeciesProtectorConstant();
|
||||
Node* species_protector = SpeciesProtectorConstant();
|
||||
Node* value =
|
||||
LoadObjectField(species_protector, PropertyCell::kValueOffset);
|
||||
Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
|
||||
@ -1155,7 +1155,7 @@ class ArrayPrototypeSliceCodeStubAssembler : public CodeStubAssembler {
|
||||
|
||||
GotoIf(IsNoElementsProtectorCellInvalid(), slow);
|
||||
|
||||
GotoIf(IsArraySpeciesProtectorCellInvalid(), slow);
|
||||
GotoIf(IsSpeciesProtectorCellInvalid(), slow);
|
||||
|
||||
// Bailout if receiver has slow elements.
|
||||
Node* elements_kind = LoadMapElementsKind(map);
|
||||
|
@ -247,7 +247,7 @@ BUILTIN(ArraySplice) {
|
||||
// If this is a subclass of Array, then call out to JS.
|
||||
!Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) ||
|
||||
// If anything with @@species has been messed with, call out to JS.
|
||||
!isolate->IsArraySpeciesLookupChainIntact())) {
|
||||
!isolate->IsSpeciesLookupChainIntact())) {
|
||||
return CallJsIntrinsic(isolate, isolate->array_splice(), args);
|
||||
}
|
||||
Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
||||
@ -1123,7 +1123,7 @@ BUILTIN(ArrayConcat) {
|
||||
// Avoid a real species read to avoid extra lookups to the array constructor
|
||||
if (V8_LIKELY(receiver->IsJSArray() &&
|
||||
Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
|
||||
isolate->IsArraySpeciesLookupChainIntact())) {
|
||||
isolate->IsSpeciesLookupChainIntact())) {
|
||||
if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
|
||||
return *result_array;
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ void PromiseBuiltinsAssembler::BranchIfPromiseSpeciesLookupChainIntact(
|
||||
GotoIfForceSlowPath(if_slow);
|
||||
GotoIfNot(WordEqual(LoadMapPrototype(promise_map), promise_prototype),
|
||||
if_slow);
|
||||
Branch(IsPromiseSpeciesProtectorCellInvalid(), if_slow, if_fast);
|
||||
Branch(IsSpeciesProtectorCellInvalid(), if_slow, if_fast);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::BranchIfPromiseThenLookupChainIntact(
|
||||
@ -1285,7 +1285,7 @@ TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) {
|
||||
LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
|
||||
GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype),
|
||||
&if_slow_constructor);
|
||||
GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor);
|
||||
GotoIf(IsSpeciesProtectorCellInvalid(), &if_slow_constructor);
|
||||
|
||||
// If the {constructor} is the Promise function, we just immediately
|
||||
// return the {value} here and don't bother wrapping it into a
|
||||
|
@ -883,7 +883,7 @@ TNode<Object> TypedArrayBuiltinsAssembler::TypedArraySpeciesConstructor(
|
||||
var_constructor = default_constructor;
|
||||
Node* map = LoadMap(exemplar);
|
||||
GotoIfNot(IsPrototypeTypedArrayPrototype(context, map), &slow);
|
||||
Branch(IsTypedArraySpeciesProtectorCellInvalid(), &slow, &done);
|
||||
Branch(IsSpeciesProtectorCellInvalid(), &slow, &done);
|
||||
|
||||
BIND(&slow);
|
||||
var_constructor = SpeciesConstructor(context, exemplar, default_constructor);
|
||||
|
@ -985,7 +985,7 @@ void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
|
||||
void CodeStubAssembler::BranchIfFastJSArrayForCopy(Node* object, Node* context,
|
||||
Label* if_true,
|
||||
Label* if_false) {
|
||||
GotoIf(IsArraySpeciesProtectorCellInvalid(), if_false);
|
||||
GotoIf(IsSpeciesProtectorCellInvalid(), if_false);
|
||||
BranchIfFastJSArray(object, context, if_true, if_false);
|
||||
}
|
||||
|
||||
@ -4525,23 +4525,9 @@ Node* CodeStubAssembler::IsPromiseThenProtectorCellInvalid() {
|
||||
return WordEqual(cell_value, invalid);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::IsArraySpeciesProtectorCellInvalid() {
|
||||
Node* CodeStubAssembler::IsSpeciesProtectorCellInvalid() {
|
||||
Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
|
||||
Node* cell = LoadRoot(Heap::kArraySpeciesProtectorRootIndex);
|
||||
Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
|
||||
return WordEqual(cell_value, invalid);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::IsTypedArraySpeciesProtectorCellInvalid() {
|
||||
Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
|
||||
Node* cell = LoadRoot(Heap::kTypedArraySpeciesProtectorRootIndex);
|
||||
Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
|
||||
return WordEqual(cell_value, invalid);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::IsPromiseSpeciesProtectorCellInvalid() {
|
||||
Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
|
||||
Node* cell = LoadRoot(Heap::kPromiseSpeciesProtectorRootIndex);
|
||||
Node* cell = LoadRoot(Heap::kSpeciesProtectorRootIndex);
|
||||
Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
|
||||
return WordEqual(cell_value, invalid);
|
||||
}
|
||||
|
@ -22,54 +22,50 @@ class StubCache;
|
||||
|
||||
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
|
||||
#define HEAP_CONSTANT_LIST(V) \
|
||||
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
|
||||
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
|
||||
V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \
|
||||
V(BooleanMap, boolean_map, BooleanMap) \
|
||||
V(CodeMap, code_map, CodeMap) \
|
||||
V(EmptyPropertyDictionary, empty_property_dictionary, \
|
||||
EmptyPropertyDictionary) \
|
||||
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
|
||||
V(EmptySlowElementDictionary, empty_slow_element_dictionary, \
|
||||
EmptySlowElementDictionary) \
|
||||
V(empty_string, empty_string, EmptyString) \
|
||||
V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \
|
||||
V(FalseValue, false_value, False) \
|
||||
V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \
|
||||
V(FixedArrayMap, fixed_array_map, FixedArrayMap) \
|
||||
V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \
|
||||
V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \
|
||||
V(FunctionTemplateInfoMap, function_template_info_map, \
|
||||
FunctionTemplateInfoMap) \
|
||||
V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \
|
||||
V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \
|
||||
V(HeapNumberMap, heap_number_map, HeapNumberMap) \
|
||||
V(iterator_symbol, iterator_symbol, IteratorSymbol) \
|
||||
V(length_string, length_string, LengthString) \
|
||||
V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \
|
||||
V(MetaMap, meta_map, MetaMap) \
|
||||
V(MinusZeroValue, minus_zero_value, MinusZero) \
|
||||
V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \
|
||||
V(NanValue, nan_value, Nan) \
|
||||
V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \
|
||||
V(NullValue, null_value, Null) \
|
||||
V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \
|
||||
V(prototype_string, prototype_string, PrototypeString) \
|
||||
V(ArraySpeciesProtector, array_species_protector, ArraySpeciesProtector) \
|
||||
V(TypedArraySpeciesProtector, typed_array_species_protector, \
|
||||
TypedArraySpeciesProtector) \
|
||||
V(PromiseSpeciesProtector, promise_species_protector, \
|
||||
PromiseSpeciesProtector) \
|
||||
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
|
||||
V(SymbolMap, symbol_map, SymbolMap) \
|
||||
V(TheHoleValue, the_hole_value, TheHole) \
|
||||
V(TransitionArrayMap, transition_array_map, TransitionArrayMap) \
|
||||
V(TrueValue, true_value, True) \
|
||||
V(Tuple2Map, tuple2_map, Tuple2Map) \
|
||||
V(Tuple3Map, tuple3_map, Tuple3Map) \
|
||||
V(UndefinedValue, undefined_value, Undefined) \
|
||||
V(WeakCellMap, weak_cell_map, WeakCellMap) \
|
||||
#define HEAP_CONSTANT_LIST(V) \
|
||||
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
|
||||
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
|
||||
V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \
|
||||
V(BooleanMap, boolean_map, BooleanMap) \
|
||||
V(CodeMap, code_map, CodeMap) \
|
||||
V(EmptyPropertyDictionary, empty_property_dictionary, \
|
||||
EmptyPropertyDictionary) \
|
||||
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
|
||||
V(EmptySlowElementDictionary, empty_slow_element_dictionary, \
|
||||
EmptySlowElementDictionary) \
|
||||
V(empty_string, empty_string, EmptyString) \
|
||||
V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \
|
||||
V(FalseValue, false_value, False) \
|
||||
V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \
|
||||
V(FixedArrayMap, fixed_array_map, FixedArrayMap) \
|
||||
V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \
|
||||
V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \
|
||||
V(FunctionTemplateInfoMap, function_template_info_map, \
|
||||
FunctionTemplateInfoMap) \
|
||||
V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \
|
||||
V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \
|
||||
V(HeapNumberMap, heap_number_map, HeapNumberMap) \
|
||||
V(iterator_symbol, iterator_symbol, IteratorSymbol) \
|
||||
V(length_string, length_string, LengthString) \
|
||||
V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \
|
||||
V(MetaMap, meta_map, MetaMap) \
|
||||
V(MinusZeroValue, minus_zero_value, MinusZero) \
|
||||
V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \
|
||||
V(NanValue, nan_value, Nan) \
|
||||
V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \
|
||||
V(NullValue, null_value, Null) \
|
||||
V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \
|
||||
V(prototype_string, prototype_string, PrototypeString) \
|
||||
V(SpeciesProtector, species_protector, SpeciesProtector) \
|
||||
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
|
||||
V(SymbolMap, symbol_map, SymbolMap) \
|
||||
V(TheHoleValue, the_hole_value, TheHole) \
|
||||
V(TransitionArrayMap, transition_array_map, TransitionArrayMap) \
|
||||
V(TrueValue, true_value, True) \
|
||||
V(Tuple2Map, tuple2_map, Tuple2Map) \
|
||||
V(Tuple3Map, tuple3_map, Tuple3Map) \
|
||||
V(UndefinedValue, undefined_value, Undefined) \
|
||||
V(WeakCellMap, weak_cell_map, WeakCellMap) \
|
||||
V(SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfoMap)
|
||||
|
||||
// Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared
|
||||
@ -1378,9 +1374,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
|
||||
Node* IsPromiseResolveProtectorCellInvalid();
|
||||
Node* IsPromiseThenProtectorCellInvalid();
|
||||
Node* IsArraySpeciesProtectorCellInvalid();
|
||||
Node* IsTypedArraySpeciesProtectorCellInvalid();
|
||||
Node* IsPromiseSpeciesProtectorCellInvalid();
|
||||
Node* IsSpeciesProtectorCellInvalid();
|
||||
|
||||
// True iff |object| is a Smi or a HeapNumber.
|
||||
TNode<BoolT> IsNumber(SloppyTNode<Object> object);
|
||||
|
@ -1481,7 +1481,7 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
|
||||
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
|
||||
|
||||
// Ensure that any changes to the Array species constructor cause deopt.
|
||||
if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
const ElementsKind kind = receiver_maps[0]->elements_kind();
|
||||
|
||||
@ -1492,7 +1492,7 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
|
||||
if (receiver_map->elements_kind() != kind) return NoChange();
|
||||
}
|
||||
|
||||
dependencies()->AssumePropertyCell(factory()->array_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
Handle<JSFunction> handle_constructor(
|
||||
JSFunction::cast(
|
||||
@ -1681,7 +1681,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
|
||||
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
|
||||
|
||||
// And ensure that any changes to the Array species constructor cause deopt.
|
||||
if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
const ElementsKind kind = receiver_maps[0]->elements_kind();
|
||||
// The output array is packed (filter doesn't visit holes).
|
||||
@ -1696,7 +1696,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
|
||||
if (receiver_map->elements_kind() != kind) return NoChange();
|
||||
}
|
||||
|
||||
dependencies()->AssumePropertyCell(factory()->array_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
Handle<Map> initial_map(
|
||||
Map::cast(native_context()->GetInitialJSArrayMap(packed_kind)));
|
||||
@ -2274,7 +2274,7 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
|
||||
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
|
||||
|
||||
// And ensure that any changes to the Array species constructor cause deopt.
|
||||
if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
const ElementsKind kind = receiver_maps[0]->elements_kind();
|
||||
|
||||
@ -2285,7 +2285,7 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
|
||||
if (receiver_map->elements_kind() != kind) return NoChange();
|
||||
}
|
||||
|
||||
dependencies()->AssumePropertyCell(factory()->array_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
// If we have unreliable maps, we need a map check.
|
||||
if (result == NodeProperties::kUnreliableReceiverMaps) {
|
||||
@ -2597,7 +2597,7 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
|
||||
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
|
||||
|
||||
// And ensure that any changes to the Array species constructor cause deopt.
|
||||
if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
if (receiver_maps.size() == 0) return NoChange();
|
||||
|
||||
@ -2610,7 +2610,7 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
|
||||
if (receiver_map->elements_kind() != kind) return NoChange();
|
||||
}
|
||||
|
||||
dependencies()->AssumePropertyCell(factory()->array_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
Node* k = jsgraph()->ZeroConstant();
|
||||
|
||||
@ -5730,7 +5730,7 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
||||
// lookup of "constructor" on JSPromise instances, whoch [[Prototype]] is
|
||||
// the initial %PromisePrototype%, and the Symbol.species lookup on the
|
||||
// %PromisePrototype%.
|
||||
if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
// Check if we know something about {receiver} already.
|
||||
ZoneHandleSet<Map> receiver_maps;
|
||||
@ -5751,7 +5751,7 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
||||
// Add a code dependency on the necessary protectors.
|
||||
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->promise_then_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->promise_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
// If the {receiver_maps} aren't reliable, we need to repeat the
|
||||
// map check here, guarded by the CALL_IC.
|
||||
@ -5878,7 +5878,7 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
|
||||
// guards the "constructor" lookup on all JSPromise instances and the
|
||||
// initial Promise.prototype, as well as the Symbol.species lookup on
|
||||
// the Promise constructor.
|
||||
if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
|
||||
if (!isolate()->IsSpeciesLookupChainIntact()) return NoChange();
|
||||
|
||||
// Check if we know something about {receiver} already.
|
||||
ZoneHandleSet<Map> receiver_maps;
|
||||
@ -5900,7 +5900,7 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
|
||||
|
||||
// Add a code dependency on the necessary protectors.
|
||||
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->promise_species_protector());
|
||||
dependencies()->AssumePropertyCell(factory()->species_protector());
|
||||
|
||||
// If the {receiver_maps} aren't reliable, we need to repeat the
|
||||
// map check here, guarded by the CALL_IC.
|
||||
|
@ -228,9 +228,7 @@ using v8::MemoryPressureLevel;
|
||||
V(Cell, array_constructor_protector, ArrayConstructorProtector) \
|
||||
V(PropertyCell, no_elements_protector, NoElementsProtector) \
|
||||
V(Cell, is_concat_spreadable_protector, IsConcatSpreadableProtector) \
|
||||
V(PropertyCell, array_species_protector, ArraySpeciesProtector) \
|
||||
V(PropertyCell, typed_array_species_protector, TypedArraySpeciesProtector) \
|
||||
V(PropertyCell, promise_species_protector, PromiseSpeciesProtector) \
|
||||
V(PropertyCell, species_protector, SpeciesProtector) \
|
||||
V(Cell, string_length_protector, StringLengthProtector) \
|
||||
V(PropertyCell, array_iterator_protector, ArrayIteratorProtector) \
|
||||
V(PropertyCell, array_buffer_neutering_protector, \
|
||||
@ -391,9 +389,7 @@ using v8::MemoryPressureLevel;
|
||||
V(SloppyArgumentsElementsMap) \
|
||||
V(SmallOrderedHashMapMap) \
|
||||
V(SmallOrderedHashSetMap) \
|
||||
V(ArraySpeciesProtector) \
|
||||
V(TypedArraySpeciesProtector) \
|
||||
V(PromiseSpeciesProtector) \
|
||||
V(SpeciesProtector) \
|
||||
V(StaleRegister) \
|
||||
V(StringLengthProtector) \
|
||||
V(StringTableMap) \
|
||||
|
@ -787,15 +787,7 @@ void Heap::CreateInitialObjects() {
|
||||
|
||||
cell = factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
|
||||
set_array_species_protector(*cell);
|
||||
|
||||
cell = factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
|
||||
set_typed_array_species_protector(*cell);
|
||||
|
||||
cell = factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
|
||||
set_promise_species_protector(*cell);
|
||||
set_species_protector(*cell);
|
||||
|
||||
Handle<Cell> string_length_overflow_cell = factory->NewCell(
|
||||
handle(Smi::FromInt(Isolate::kProtectorValid), isolate()));
|
||||
|
@ -133,7 +133,7 @@ bool Isolate::IsArrayConstructorIntact() {
|
||||
return array_constructor_cell->value() == Smi::FromInt(kProtectorValid);
|
||||
}
|
||||
|
||||
bool Isolate::IsArraySpeciesLookupChainIntact() {
|
||||
bool Isolate::IsSpeciesLookupChainIntact() {
|
||||
// Note: It would be nice to have debug checks to make sure that the
|
||||
// species protector is accurate, but this would be hard to do for most of
|
||||
// what the protector stands for:
|
||||
@ -146,19 +146,7 @@ bool Isolate::IsArraySpeciesLookupChainIntact() {
|
||||
// done here. In place, there are mjsunit tests harmony/array-species* which
|
||||
// ensure that behavior is correct in various invalid protector cases.
|
||||
|
||||
PropertyCell* species_cell = heap()->array_species_protector();
|
||||
return species_cell->value()->IsSmi() &&
|
||||
Smi::ToInt(species_cell->value()) == kProtectorValid;
|
||||
}
|
||||
|
||||
bool Isolate::IsTypedArraySpeciesLookupChainIntact() {
|
||||
PropertyCell* species_cell = heap()->typed_array_species_protector();
|
||||
return species_cell->value()->IsSmi() &&
|
||||
Smi::ToInt(species_cell->value()) == kProtectorValid;
|
||||
}
|
||||
|
||||
bool Isolate::IsPromiseSpeciesLookupChainIntact() {
|
||||
PropertyCell* species_cell = heap()->promise_species_protector();
|
||||
PropertyCell* species_cell = heap()->species_protector();
|
||||
return species_cell->value()->IsSmi() &&
|
||||
Smi::ToInt(species_cell->value()) == kProtectorValid;
|
||||
}
|
||||
|
@ -3573,28 +3573,11 @@ void Isolate::InvalidateArrayConstructorProtector() {
|
||||
DCHECK(!IsArrayConstructorIntact());
|
||||
}
|
||||
|
||||
void Isolate::InvalidateArraySpeciesProtector() {
|
||||
DCHECK(factory()->array_species_protector()->value()->IsSmi());
|
||||
DCHECK(IsArraySpeciesLookupChainIntact());
|
||||
factory()->array_species_protector()->set_value(
|
||||
Smi::FromInt(kProtectorInvalid));
|
||||
DCHECK(!IsArraySpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
void Isolate::InvalidateTypedArraySpeciesProtector() {
|
||||
DCHECK(factory()->typed_array_species_protector()->value()->IsSmi());
|
||||
DCHECK(IsTypedArraySpeciesLookupChainIntact());
|
||||
factory()->typed_array_species_protector()->set_value(
|
||||
Smi::FromInt(kProtectorInvalid));
|
||||
DCHECK(!IsTypedArraySpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
void Isolate::InvalidatePromiseSpeciesProtector() {
|
||||
DCHECK(factory()->promise_species_protector()->value()->IsSmi());
|
||||
DCHECK(IsPromiseSpeciesLookupChainIntact());
|
||||
factory()->promise_species_protector()->set_value(
|
||||
Smi::FromInt(kProtectorInvalid));
|
||||
DCHECK(!IsPromiseSpeciesLookupChainIntact());
|
||||
void Isolate::InvalidateSpeciesProtector() {
|
||||
DCHECK(factory()->species_protector()->value()->IsSmi());
|
||||
DCHECK(IsSpeciesLookupChainIntact());
|
||||
factory()->species_protector()->set_value(Smi::FromInt(kProtectorInvalid));
|
||||
DCHECK(!IsSpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
void Isolate::InvalidateStringLengthOverflowProtector() {
|
||||
|
@ -1080,9 +1080,7 @@ class Isolate : private HiddenFactory {
|
||||
bool IsNoElementsProtectorIntact(Context* context);
|
||||
bool IsNoElementsProtectorIntact();
|
||||
|
||||
inline bool IsArraySpeciesLookupChainIntact();
|
||||
inline bool IsTypedArraySpeciesLookupChainIntact();
|
||||
inline bool IsPromiseSpeciesLookupChainIntact();
|
||||
inline bool IsSpeciesLookupChainIntact();
|
||||
bool IsIsConcatSpreadableLookupChainIntact();
|
||||
bool IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver);
|
||||
inline bool IsStringLengthOverflowIntact();
|
||||
@ -1122,9 +1120,7 @@ class Isolate : private HiddenFactory {
|
||||
UpdateNoElementsProtectorOnSetElement(object);
|
||||
}
|
||||
void InvalidateArrayConstructorProtector();
|
||||
void InvalidateArraySpeciesProtector();
|
||||
void InvalidateTypedArraySpeciesProtector();
|
||||
void InvalidatePromiseSpeciesProtector();
|
||||
void InvalidateSpeciesProtector();
|
||||
void InvalidateIsConcatSpreadableProtector();
|
||||
void InvalidateStringLengthOverflowProtector();
|
||||
void InvalidateArrayIteratorProtector();
|
||||
|
@ -272,27 +272,14 @@ void LookupIterator::InternalUpdateProtector() {
|
||||
if (isolate_->bootstrapper()->IsActive()) return;
|
||||
|
||||
if (*name_ == heap()->constructor_string()) {
|
||||
if (!isolate_->IsArraySpeciesLookupChainIntact() &&
|
||||
!isolate_->IsTypedArraySpeciesLookupChainIntact() &&
|
||||
!isolate_->IsPromiseSpeciesLookupChainIntact())
|
||||
return;
|
||||
if (!isolate_->IsSpeciesLookupChainIntact()) return;
|
||||
// Setting the constructor property could change an instance's @@species
|
||||
if (holder_->IsJSArray()) {
|
||||
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
|
||||
if (holder_->IsJSArray() || holder_->IsJSPromise() ||
|
||||
holder_->IsJSTypedArray()) {
|
||||
isolate_->CountUsage(
|
||||
v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
|
||||
isolate_->InvalidateArraySpeciesProtector();
|
||||
return;
|
||||
} else if (holder_->IsJSPromise()) {
|
||||
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidatePromiseSpeciesProtector();
|
||||
return;
|
||||
} else if (holder_->IsJSTypedArray()) {
|
||||
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidateTypedArraySpeciesProtector();
|
||||
return;
|
||||
}
|
||||
if (holder_->map()->is_prototype_map()) {
|
||||
isolate_->InvalidateSpeciesProtector();
|
||||
} else if (holder_->map()->is_prototype_map()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
// Setting the constructor of Array.prototype, Promise.prototype or
|
||||
// %TypedArray%.prototype of any realm also needs to invalidate the
|
||||
@ -301,20 +288,14 @@ void LookupIterator::InternalUpdateProtector() {
|
||||
// have different prototypes for each type, and their parent prototype is
|
||||
// pointing the same TYPED_ARRAY_PROTOTYPE.
|
||||
if (isolate_->IsInAnyContext(*holder_,
|
||||
Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
|
||||
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
|
||||
isolate_->CountUsage(
|
||||
v8::Isolate::UseCounterFeature::kArrayPrototypeConstructorModified);
|
||||
isolate_->InvalidateArraySpeciesProtector();
|
||||
} else if (isolate_->IsInAnyContext(*holder_,
|
||||
Context::PROMISE_PROTOTYPE_INDEX)) {
|
||||
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidatePromiseSpeciesProtector();
|
||||
} else if (isolate_->IsInAnyContext(
|
||||
holder_->map()->prototype(),
|
||||
Context::TYPED_ARRAY_PROTOTYPE_INDEX)) {
|
||||
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidateTypedArraySpeciesProtector();
|
||||
Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
|
||||
isolate_->IsInAnyContext(*holder_,
|
||||
Context::PROMISE_PROTOTYPE_INDEX) ||
|
||||
isolate_->IsInAnyContext(holder_->map()->prototype(),
|
||||
Context::TYPED_ARRAY_PROTOTYPE_INDEX)) {
|
||||
isolate_->CountUsage(v8::Isolate::UseCounterFeature::
|
||||
kArrayPrototypeConstructorModified);
|
||||
isolate_->InvalidateSpeciesProtector();
|
||||
}
|
||||
}
|
||||
} else if (*name_ == heap()->next_string()) {
|
||||
@ -326,24 +307,15 @@ void LookupIterator::InternalUpdateProtector() {
|
||||
isolate_->InvalidateArrayIteratorProtector();
|
||||
}
|
||||
} else if (*name_ == heap()->species_symbol()) {
|
||||
if (!isolate_->IsArraySpeciesLookupChainIntact() &&
|
||||
!isolate_->IsTypedArraySpeciesLookupChainIntact() &&
|
||||
!isolate_->IsPromiseSpeciesLookupChainIntact())
|
||||
return;
|
||||
if (!isolate_->IsSpeciesLookupChainIntact()) return;
|
||||
// Setting the Symbol.species property of any Array, Promise or TypedArray
|
||||
// constructor invalidates the @@species protector
|
||||
if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX)) {
|
||||
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
|
||||
if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX) ||
|
||||
isolate_->IsInAnyContext(*holder_, Context::PROMISE_FUNCTION_INDEX) ||
|
||||
IsTypedArrayFunctionInAnyContext(isolate_, *holder_)) {
|
||||
isolate_->CountUsage(
|
||||
v8::Isolate::UseCounterFeature::kArraySpeciesModified);
|
||||
isolate_->InvalidateArraySpeciesProtector();
|
||||
} else if (isolate_->IsInAnyContext(*holder_,
|
||||
Context::PROMISE_FUNCTION_INDEX)) {
|
||||
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidatePromiseSpeciesProtector();
|
||||
} else if (IsTypedArrayFunctionInAnyContext(isolate_, *holder_)) {
|
||||
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
|
||||
isolate_->InvalidateTypedArraySpeciesProtector();
|
||||
isolate_->InvalidateSpeciesProtector();
|
||||
}
|
||||
} else if (*name_ == heap()->is_concat_spreadable_symbol()) {
|
||||
if (!isolate_->IsIsConcatSpreadableLookupChainIntact()) return;
|
||||
|
@ -2370,7 +2370,7 @@ MaybeHandle<Object> Object::ArraySpeciesConstructor(
|
||||
Handle<Object> default_species = isolate->array_function();
|
||||
if (original_array->IsJSArray() &&
|
||||
Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
|
||||
isolate->IsArraySpeciesLookupChainIntact()) {
|
||||
isolate->IsSpeciesLookupChainIntact()) {
|
||||
return default_species;
|
||||
}
|
||||
Handle<Object> constructor = isolate->factory()->undefined_value();
|
||||
|
@ -396,7 +396,7 @@ RUNTIME_FUNCTION(Runtime_TrySliceSimpleNonFastElements) {
|
||||
// implementation.
|
||||
if (receiver->IsJSArray()) {
|
||||
// This "fastish" path must make sure the destination array is a JSArray.
|
||||
if (!isolate->IsArraySpeciesLookupChainIntact() ||
|
||||
if (!isolate->IsSpeciesLookupChainIntact() ||
|
||||
!JSArray::cast(*receiver)->HasArrayPrototype(isolate)) {
|
||||
return Smi::FromInt(0);
|
||||
}
|
||||
|
@ -841,24 +841,11 @@ TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
|
||||
|
||||
#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_TypedArraySpeciesProtector) {
|
||||
RUNTIME_FUNCTION(Runtime_SpeciesProtector) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
return isolate->heap()->ToBoolean(
|
||||
isolate->IsTypedArraySpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_PromiseSpeciesProtector) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
return isolate->heap()->ToBoolean(
|
||||
isolate->IsPromiseSpeciesLookupChainIntact());
|
||||
return isolate->heap()->ToBoolean(isolate->IsSpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
// Take a compiled wasm module, serialize it and copy the buffer into an array
|
||||
|
@ -588,9 +588,7 @@ namespace internal {
|
||||
F(SetForceSlowPath, 1, 1) \
|
||||
F(SetWasmCompileControls, 2, 1) \
|
||||
F(SetWasmInstantiateControls, 0, 1) \
|
||||
F(ArraySpeciesProtector, 0, 1) \
|
||||
F(TypedArraySpeciesProtector, 0, 1) \
|
||||
F(PromiseSpeciesProtector, 0, 1) \
|
||||
F(SpeciesProtector, 0, 1) \
|
||||
F(SystemBreak, 0, 1) \
|
||||
F(TraceEnter, 0, 1) \
|
||||
F(TraceExit, 1, 1) \
|
||||
|
@ -117,12 +117,12 @@ void TestSpeciesProtector(char* code,
|
||||
|
||||
v8::internal::Isolate* i_isolate =
|
||||
reinterpret_cast<v8::internal::Isolate*>(isolate);
|
||||
CHECK(i_isolate->IsTypedArraySpeciesLookupChainIntact());
|
||||
CHECK(i_isolate->IsSpeciesLookupChainIntact());
|
||||
CompileRun(code);
|
||||
if (invalidates_species_protector) {
|
||||
CHECK(!i_isolate->IsTypedArraySpeciesLookupChainIntact());
|
||||
CHECK(!i_isolate->IsSpeciesLookupChainIntact());
|
||||
} else {
|
||||
CHECK(i_isolate->IsTypedArraySpeciesLookupChainIntact());
|
||||
CHECK(i_isolate->IsSpeciesLookupChainIntact());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> my_typed_array = CompileRun("MyTypedArray");
|
||||
|
@ -18,7 +18,7 @@ assertEquals(1, x.concat([1])[0]);
|
||||
class MyArray extends Array { }
|
||||
|
||||
Object.defineProperty(x, 'constructor', {get() { return MyArray; }});
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -19,7 +19,7 @@ class MyArray extends Array { }
|
||||
|
||||
Object.prototype.constructor = MyArray;
|
||||
delete Array.prototype.constructor;
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -18,7 +18,7 @@ assertEquals(1, x.concat([1])[0]);
|
||||
class MyArray extends Array { }
|
||||
|
||||
x.constructor = MyArray;
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -19,7 +19,7 @@ class MyArray extends Array { }
|
||||
|
||||
Object.prototype[Symbol.species] = MyArray;
|
||||
delete Array[Symbol.species];
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -18,7 +18,7 @@ assertEquals(1, x.concat([1])[0]);
|
||||
class MyArray extends Array { }
|
||||
|
||||
Object.defineProperty(Array, Symbol.species, {value: MyArray});
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -18,7 +18,7 @@ assertEquals(1, x.concat([1])[0]);
|
||||
class MyArray extends Array { }
|
||||
|
||||
Array.prototype.constructor = MyArray;
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -18,7 +18,7 @@ assertEquals(1, x.concat([1])[0]);
|
||||
class MyArray extends Array { }
|
||||
|
||||
x.__proto__ = MyArray.prototype;
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
|
||||
assertEquals(MyArray, x.map(()=>{}).constructor);
|
||||
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
||||
|
@ -425,7 +425,7 @@ function toSlowMode(re) {
|
||||
{
|
||||
const re = /./;
|
||||
const result = re.exec("a");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertTrue(result.hasOwnProperty('groups'));
|
||||
assertArrayEquals(["a"], result);
|
||||
@ -433,7 +433,7 @@ function toSlowMode(re) {
|
||||
assertEquals(undefined, result.groups);
|
||||
|
||||
Array.prototype.groups = { a: "b" };
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals("$<a>", "a".replace(re, "$<a>"));
|
||||
Array.prototype.groups = undefined;
|
||||
}
|
||||
@ -441,7 +441,7 @@ function toSlowMode(re) {
|
||||
{
|
||||
const re = toSlowMode(/./);
|
||||
const result = re.exec("a");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertTrue(result.hasOwnProperty('groups'));
|
||||
assertArrayEquals(["a"], result);
|
||||
@ -449,7 +449,7 @@ function toSlowMode(re) {
|
||||
assertEquals(undefined, result.groups);
|
||||
|
||||
Array.prototype.groups = { a: "b" };
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals("$<a>", "a".replace(re, "$<a>"));
|
||||
Array.prototype.groups = undefined;
|
||||
}
|
||||
@ -457,7 +457,7 @@ function toSlowMode(re) {
|
||||
{
|
||||
const re = /(?<a>a).|(?<x>x)/;
|
||||
const result = re.exec("ab");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertTrue(result.hasOwnProperty('groups'));
|
||||
assertArrayEquals(["ab", "a", undefined], result);
|
||||
@ -467,7 +467,7 @@ function toSlowMode(re) {
|
||||
// a is a matched named capture, b is an unmatched named capture, and z
|
||||
// is not a named capture.
|
||||
Array.prototype.groups = { a: "b", x: "y", z: "z" };
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals("a", "ab".replace(re, "$<a>"));
|
||||
assertEquals("", "ab".replace(re, "$<x>"));
|
||||
assertEquals("", "ab".replace(re, "$<z>"));
|
||||
@ -477,7 +477,7 @@ function toSlowMode(re) {
|
||||
{
|
||||
const re = toSlowMode(/(?<a>a).|(?<x>x)/);
|
||||
const result = re.exec("ab");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertTrue(result.hasOwnProperty('groups'));
|
||||
assertArrayEquals(["ab", "a", undefined], result);
|
||||
@ -487,7 +487,7 @@ function toSlowMode(re) {
|
||||
// a is a matched named capture, b is an unmatched named capture, and z
|
||||
// is not a named capture.
|
||||
Array.prototype.groups = { a: "b", x: "y", z: "z" };
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals("a", "ab".replace(re, "$<a>"));
|
||||
assertEquals("", "ab".replace(re, "$<x>"));
|
||||
assertEquals("", "ab".replace(re, "$<z>"));
|
||||
@ -506,13 +506,13 @@ function toSlowMode(re) {
|
||||
|
||||
const re = new FakeRegExp();
|
||||
const result = re.exec("ab");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertFalse(result.hasOwnProperty('groups'));
|
||||
|
||||
Array.prototype.groups = { a: "b" };
|
||||
Array.prototype.groups.__proto__.b = "c";
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals("b", "ab".replace(re, "$<a>"));
|
||||
assertEquals("c", "ab".replace(re, "$<b>"));
|
||||
Array.prototype.groups = undefined;
|
||||
@ -531,7 +531,7 @@ function toSlowMode(re) {
|
||||
|
||||
const re = new FakeRegExp();
|
||||
const result = re.exec("ab");
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
assertEquals(result.__proto__, Array.prototype);
|
||||
assertTrue(result.hasOwnProperty('groups'));
|
||||
assertEquals({ a: "b" }, result.groups);
|
||||
|
@ -16,7 +16,7 @@ f("make it generic", 0, 0);
|
||||
|
||||
(function TestSpeciesProtector() {
|
||||
function MyArray() {}
|
||||
assertTrue(%ArraySpeciesProtector());
|
||||
assertTrue(%SpeciesProtector());
|
||||
f(Array.prototype, "constructor", MyArray);
|
||||
assertFalse(%ArraySpeciesProtector());
|
||||
assertFalse(%SpeciesProtector());
|
||||
})();
|
||||
|
@ -333,15 +333,13 @@ KNOWN_OBJECTS = {
|
||||
("OLD_SPACE", 0x02659): "EmptyWeakCell",
|
||||
("OLD_SPACE", 0x026e1): "NoElementsProtector",
|
||||
("OLD_SPACE", 0x02709): "IsConcatSpreadableProtector",
|
||||
("OLD_SPACE", 0x02719): "ArraySpeciesProtector",
|
||||
("OLD_SPACE", 0x02741): "TypedArraySpeciesProtector",
|
||||
("OLD_SPACE", 0x02769): "PromiseSpeciesProtector",
|
||||
("OLD_SPACE", 0x02791): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x027a1): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x027c9): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02851): "InfinityValue",
|
||||
("OLD_SPACE", 0x02861): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02871): "MinusInfinityValue",
|
||||
("OLD_SPACE", 0x02719): "SpeciesProtector",
|
||||
("OLD_SPACE", 0x02741): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x02751): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x02779): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02801): "InfinityValue",
|
||||
("OLD_SPACE", 0x02811): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02821): "MinusInfinityValue",
|
||||
}
|
||||
|
||||
# List of known V8 Frame Markers.
|
||||
|
Loading…
Reference in New Issue
Block a user