Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index 21269fdc65bae7854fa2604358c63ee423207902..78074e27513bca2a75833a0a0521d879a09ec6bf 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -15,6 +15,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
: CodeStubAssembler(state), |
k_(this, MachineRepresentation::kTagged), |
a_(this, MachineRepresentation::kTagged), |
+ force_slow_(this, MachineRepresentation::kTagged, SmiConstant(0)), |
to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {} |
typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)> |
@@ -195,8 +196,37 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} |
Node* MapResultGenerator() { |
- // 5. Let A be ? ArraySpeciesCreate(O, len). |
- return ArraySpeciesCreate(context(), o(), len_); |
+ VARIABLE(species_constructor, MachineRepresentation::kTagged); |
+ Label slow_path(this), done(this, &species_constructor); |
+ GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &slow_path); |
+ Node* o_map = LoadMap(o()); |
+ Node* const initial_array_prototype = LoadContextElement( |
+ LoadNativeContext(context()), Context::INITIAL_ARRAY_PROTOTYPE_INDEX); |
+ Node* proto = LoadMapPrototype(o_map); |
+ GotoIf(WordNotEqual(proto, initial_array_prototype), &slow_path); |
+ |
+ Node* species_protector = SpeciesProtectorConstant(); |
+ Node* value = LoadObjectField(species_protector, Cell::kValueOffset); |
+ Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid); |
+ GotoIf(WordEqual(value, protector_invalid), &slow_path); |
+ |
+ Node* const initial_array_constructor = LoadContextElement( |
+ LoadNativeContext(context()), Context::ARRAY_FUNCTION_INDEX); |
+ species_constructor.Bind(initial_array_constructor); |
+ Goto(&done); |
+ |
+ BIND(&slow_path); |
+ { |
+ // 5. Let A be ? ArraySpeciesCreate(O, len). |
+ Node* constructor = |
+ CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()); |
+ species_constructor.Bind(constructor); |
+ force_slow_.Bind(SmiConstant(1)); |
danno
2017/04/29 09:27:14
Would it be a little cleaner to just jump to the s
|
+ Goto(&done); |
+ } |
+ BIND(&done); |
danno
2017/04/29 09:27:14
I am a little surprised this works... you change t
|
+ return ConstructJS(CodeFactory::Construct(isolate()), context(), |
+ species_constructor.value(), len_); |
} |
Node* MapProcessor(Node* k_value, Node* k) { |
@@ -215,6 +245,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Label fast(this); |
Label runtime(this); |
Label object_push_pre(this), object_push(this), double_push(this); |
+ GotoIf(WordEqual(force_slow(), SmiConstant(1)), &runtime); |
BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
&fast, &runtime); |
@@ -270,6 +301,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* len() { return len_; } |
Node* callbackfn() { return callbackfn_; } |
Node* this_arg() { return this_arg_; } |
+ Node* force_slow() { return force_slow_.value(); } |
Node* k() { return k_.value(); } |
Node* a() { return a_.value(); } |
@@ -384,6 +416,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
o_ = o; |
len_ = len; |
to_.Bind(to); |
+ force_slow_.Bind(SmiConstant(1)); |
} |
void GenerateIteratingTypedArrayBuiltinBody( |
@@ -710,6 +743,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* new_target_ = nullptr; |
Variable k_; |
Variable a_; |
+ Variable force_slow_; |
Variable to_; |
}; |