Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-utils-gen.h" | 5 #include "src/builtins/builtins-utils-gen.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-stub-assembler.h" | 7 #include "src/code-stub-assembler.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| 11 | 11 |
| 12 class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { | 12 class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| 13 public: | 13 public: |
| 14 explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state) | 14 explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state) |
| 15 : CodeStubAssembler(state), to_(this, MachineRepresentation::kTagged) { | 15 : CodeStubAssembler(state), |
| 16 to_.Bind(SmiConstant(0)); | 16 k_(this, MachineRepresentation::kTagged, SmiConstant(0)), |
| 17 a_(this, MachineRepresentation::kTagged, SmiConstant(0)), | |
| 18 to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {} | |
| 19 | |
| 20 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)> | |
| 21 BuiltinResultGenerator; | |
| 22 | |
| 23 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)> | |
| 24 BuiltinResultIndexInitializer; | |
| 25 | |
| 26 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm, | |
| 27 Node* k_value, Node* k)> | |
| 28 CallResultProcessor; | |
| 29 | |
| 30 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)> | |
| 31 PostLoopAction; | |
| 32 | |
| 33 Node* ForEachResultGenerator() { return UndefinedConstant(); } | |
| 34 | |
| 35 Node* ForEachProcessor(Node* k_value, Node* k) { | |
| 36 CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(), | |
| 37 k_value, k, o()); | |
| 38 return a(); | |
| 17 } | 39 } |
| 18 | 40 |
| 19 typedef std::function<Node*(Node* context, Node* o, Node* len)> | 41 Node* SomeResultGenerator() { return FalseConstant(); } |
| 20 BuiltinResultGenerator; | 42 |
| 21 typedef std::function<void(Node* context, Node* a)> | 43 Node* SomeProcessor(Node* k_value, Node* k) { |
| 22 BuiltinResultIndexInitializer; | 44 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), |
| 23 typedef std::function<void(Node* context, Node* value, Node* a, | 45 this_arg(), k_value, k, o()); |
| 24 Node* callback_result)> | 46 Label false_continue(this), return_true(this); |
| 25 CallResultProcessor; | 47 BranchIfToBooleanIsTrue(value, &return_true, &false_continue); |
| 48 Bind(&return_true); | |
| 49 Return(TrueConstant()); | |
| 50 Bind(&false_continue); | |
| 51 return a(); | |
| 52 } | |
| 53 | |
| 54 Node* EveryResultGenerator() { return TrueConstant(); } | |
| 55 | |
| 56 Node* EveryProcessor(Node* k_value, Node* k) { | |
| 57 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), | |
| 58 this_arg(), k_value, k, o()); | |
| 59 Label true_continue(this), return_false(this); | |
| 60 BranchIfToBooleanIsTrue(value, &true_continue, &return_false); | |
| 61 Bind(&return_false); | |
| 62 Return(FalseConstant()); | |
| 63 Bind(&true_continue); | |
| 64 return a(); | |
| 65 } | |
| 66 | |
| 67 Node* ReduceResultGenerator() { | |
| 68 Variable a(this, MachineRepresentation::kTagged, UndefinedConstant()); | |
| 69 Label no_initial_value(this), has_initial_value(this), done(this, {&a}); | |
| 70 | |
| 71 // 8. If initialValue is present, then | |
| 72 Node* parent_frame_ptr = LoadParentFramePointer(); | |
| 73 Node* marker_or_function = LoadBufferObject( | |
| 74 parent_frame_ptr, CommonFrameConstants::kContextOrFrameTypeOffset); | |
| 75 GotoIf( | |
| 76 MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR), | |
| 77 &has_initial_value); | |
| 78 | |
| 79 // Has arguments adapter, check count. | |
| 80 Node* adapted_parameter_count = LoadBufferObject( | |
| 81 parent_frame_ptr, ArgumentsAdaptorFrameConstants::kLengthOffset); | |
| 82 Branch(SmiLessThan(adapted_parameter_count, | |
| 83 SmiConstant(IteratingArrayBuiltinDescriptor::kThisArg)), | |
| 84 &no_initial_value, &has_initial_value); | |
| 85 | |
| 86 // a. Set accumulator to initialValue. | |
| 87 Bind(&has_initial_value); | |
| 88 a.Bind(this_arg()); | |
| 89 Goto(&done); | |
| 90 | |
| 91 // 9. Else initialValue is not present, | |
| 92 Bind(&no_initial_value); | |
| 93 | |
| 94 // a. Let kPresent be false. | |
| 95 a.Bind(TheHoleConstant()); | |
| 96 Goto(&done); | |
| 97 Bind(&done); | |
| 98 return a.value(); | |
| 99 } | |
| 100 | |
| 101 Node* ReduceProcessor(Node* k_value, Node* k) { | |
| 102 Variable result(this, MachineRepresentation::kTagged); | |
| 103 Label done(this, {&result}), initial(this); | |
| 104 GotoIf(WordEqual(a(), TheHoleConstant()), &initial); | |
| 105 result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), | |
| 106 UndefinedConstant(), a(), k_value, k, o())); | |
| 107 Goto(&done); | |
| 108 | |
| 109 Bind(&initial); | |
| 110 result.Bind(k_value); | |
| 111 Goto(&done); | |
| 112 | |
| 113 Bind(&done); | |
| 114 return result.value(); | |
| 115 } | |
| 116 | |
| 117 void ReducePostLoopAction() { | |
| 118 Label ok(this); | |
| 119 GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok); | |
| 120 CallRuntime(Runtime::kThrowTypeError, context(), | |
| 121 SmiConstant(MessageTemplate::kReduceNoInitial)); | |
| 122 Unreachable(); | |
| 123 Bind(&ok); | |
| 124 } | |
| 125 | |
| 126 Node* FilterResultGenerator() { | |
| 127 // 7. Let A be ArraySpeciesCreate(O, 0). | |
| 128 return ArraySpeciesCreate(context(), o(), SmiConstant(0)); | |
| 129 } | |
| 130 | |
| 131 void FilterResultIndexReinitializer() { | |
| 132 Variable merged_length(this, MachineRepresentation::kTagged); | |
| 133 Label has_length(this, &merged_length), not_js_array(this); | |
| 134 GotoIf(DoesntHaveInstanceType(a(), JS_ARRAY_TYPE), ¬_js_array); | |
| 135 merged_length.Bind(LoadJSArrayLength(a())); | |
| 136 Goto(&has_length); | |
| 137 Bind(¬_js_array); | |
| 138 Node* len_property = | |
| 139 GetProperty(context(), a(), isolate()->factory()->length_string()); | |
| 140 merged_length.Bind( | |
| 141 CallStub(CodeFactory::ToLength(isolate()), context(), len_property)); | |
| 142 Goto(&has_length); | |
| 143 Bind(&has_length); | |
| 144 Node* len = merged_length.value(); | |
| 145 | |
| 146 to_.Bind(len); | |
| 147 } | |
| 148 | |
| 149 Node* FilterProcessor(Node* k_value, Node* k) { | |
| 150 Node* callback_result = CallJS(CodeFactory::Call(isolate()), context(), | |
| 151 callbackfn(), this_arg(), k_value, k, o()); | |
| 152 Label true_continue(this, &to_), false_continue(this); | |
| 153 BranchIfToBooleanIsTrue(callback_result, &true_continue, &false_continue); | |
| 154 Bind(&true_continue); | |
| 155 | |
| 156 // 1. let status be CreateDataPropertyOrThrow(A, ToString(to), kValue). | |
| 157 // 2. ReturnIfAbrupt(status) | |
| 158 Node* const p_to = ToString(context(), to_.value()); | |
| 159 CallRuntime(Runtime::kCreateDataProperty, context(), a(), p_to, k_value); | |
| 160 | |
| 161 // 3. Increase to by 1. | |
| 162 to_.Bind(NumberInc(to_.value())); | |
| 163 Goto(&false_continue); | |
| 164 Bind(&false_continue); | |
| 165 return a(); | |
| 166 } | |
| 167 | |
| 168 void NullPostLoopAction() {} | |
| 169 | |
| 170 void NullResultIndexReinitializer() {} | |
| 171 | |
| 172 protected: | |
| 173 Node* context() { return context_; } | |
| 174 Node* o() { return o_; } | |
| 175 Node* len() { return len_; } | |
| 176 Node* callbackfn() { return callbackfn_; } | |
| 177 Node* this_arg() { return this_arg_; } | |
| 178 Node* k() { return k_.value(); } | |
| 179 Node* a() { return a_.value(); } | |
| 26 | 180 |
| 27 void GenerateIteratingArrayBuiltinBody( | 181 void GenerateIteratingArrayBuiltinBody( |
| 28 const char* name, const BuiltinResultGenerator& generator, | 182 const char* name, const BuiltinResultGenerator& generator, |
| 29 const CallResultProcessor& processor, | 183 const CallResultProcessor& processor, const PostLoopAction& action, |
| 30 const Callable& slow_case_continuation) { | 184 const Callable& slow_case_continuation) { |
| 31 // TODO(ishell): use constants from Descriptor once the JSFunction linkage | 185 // TODO(ishell): use constants from Descriptor once the JSFunction linkage |
| 32 // arguments are reordered. | 186 // arguments are reordered. |
| 33 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); | 187 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); |
| 34 Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback); | 188 callbackfn_ = Parameter(IteratingArrayBuiltinDescriptor::kCallback); |
| 35 Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); | 189 this_arg_ = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); |
| 36 Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext); | 190 context_ = Parameter(IteratingArrayBuiltinDescriptor::kContext); |
| 37 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); | 191 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); |
| 38 | 192 |
| 39 Variable k(this, MachineRepresentation::kTagged, SmiConstant(0)); | 193 k_.Bind(SmiConstant(0)); |
| 40 Label non_array(this), slow(this, &k), array_changes(this, &k); | 194 a_.Bind(UndefinedConstant()); |
| 195 | |
| 196 Label non_array(this), slow(this, {&k_, &a_, &to_}), | |
| 197 array_changes(this, {&k_, &a_, &to_}); | |
| 41 | 198 |
| 42 // TODO(danno): Seriously? Do we really need to throw the exact error | 199 // TODO(danno): Seriously? Do we really need to throw the exact error |
| 43 // message on null and undefined so that the webkit tests pass? | 200 // message on null and undefined so that the webkit tests pass? |
| 44 Label throw_null_undefined_exception(this, Label::kDeferred); | 201 Label throw_null_undefined_exception(this, Label::kDeferred); |
| 45 GotoIf(WordEqual(receiver, NullConstant()), | 202 GotoIf(WordEqual(receiver, NullConstant()), |
| 46 &throw_null_undefined_exception); | 203 &throw_null_undefined_exception); |
| 47 GotoIf(WordEqual(receiver, UndefinedConstant()), | 204 GotoIf(WordEqual(receiver, UndefinedConstant()), |
| 48 &throw_null_undefined_exception); | 205 &throw_null_undefined_exception); |
| 49 | 206 |
| 50 // By the book: taken directly from the ECMAScript 2015 specification | 207 // By the book: taken directly from the ECMAScript 2015 specification |
| 51 | 208 |
| 52 // 1. Let O be ToObject(this value). | 209 // 1. Let O be ToObject(this value). |
| 53 // 2. ReturnIfAbrupt(O) | 210 // 2. ReturnIfAbrupt(O) |
| 54 Node* o = CallStub(CodeFactory::ToObject(isolate()), context, receiver); | 211 o_ = CallStub(CodeFactory::ToObject(isolate()), context(), receiver); |
| 55 | 212 |
| 56 // 3. Let len be ToLength(Get(O, "length")). | 213 // 3. Let len be ToLength(Get(O, "length")). |
| 57 // 4. ReturnIfAbrupt(len). | 214 // 4. ReturnIfAbrupt(len). |
| 58 Variable merged_length(this, MachineRepresentation::kTagged); | 215 Variable merged_length(this, MachineRepresentation::kTagged); |
| 59 Label has_length(this, &merged_length), not_js_array(this); | 216 Label has_length(this, &merged_length), not_js_array(this); |
| 60 GotoIf(DoesntHaveInstanceType(o, JS_ARRAY_TYPE), ¬_js_array); | 217 GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), ¬_js_array); |
| 61 merged_length.Bind(LoadJSArrayLength(o)); | 218 merged_length.Bind(LoadJSArrayLength(o())); |
| 62 Goto(&has_length); | 219 Goto(&has_length); |
| 63 Bind(¬_js_array); | 220 Bind(¬_js_array); |
| 64 Node* len_property = | 221 Node* len_property = |
| 65 GetProperty(context, o, isolate()->factory()->length_string()); | 222 GetProperty(context(), o(), isolate()->factory()->length_string()); |
| 66 merged_length.Bind( | 223 merged_length.Bind( |
| 67 CallStub(CodeFactory::ToLength(isolate()), context, len_property)); | 224 CallStub(CodeFactory::ToLength(isolate()), context(), len_property)); |
| 68 Goto(&has_length); | 225 Goto(&has_length); |
| 69 Bind(&has_length); | 226 Bind(&has_length); |
| 70 Node* len = merged_length.value(); | 227 len_ = merged_length.value(); |
| 71 | 228 |
| 72 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. | 229 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. |
| 73 Label type_exception(this, Label::kDeferred); | 230 Label type_exception(this, Label::kDeferred); |
| 74 Label done(this); | 231 Label done(this); |
| 75 GotoIf(TaggedIsSmi(callbackfn), &type_exception); | 232 GotoIf(TaggedIsSmi(callbackfn()), &type_exception); |
| 76 Branch(IsCallableMap(LoadMap(callbackfn)), &done, &type_exception); | 233 Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception); |
| 77 | 234 |
| 78 Bind(&throw_null_undefined_exception); | 235 Bind(&throw_null_undefined_exception); |
| 79 { | 236 { |
| 80 CallRuntime( | 237 CallRuntime( |
| 81 Runtime::kThrowTypeError, context, | 238 Runtime::kThrowTypeError, context(), |
| 82 SmiConstant(MessageTemplate::kCalledOnNullOrUndefined), | 239 SmiConstant(MessageTemplate::kCalledOnNullOrUndefined), |
| 83 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name))); | 240 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name))); |
| 84 Unreachable(); | 241 Unreachable(); |
| 85 } | 242 } |
| 86 | 243 |
| 87 Bind(&type_exception); | 244 Bind(&type_exception); |
| 88 { | 245 { |
| 89 CallRuntime(Runtime::kThrowTypeError, context, | 246 CallRuntime(Runtime::kThrowTypeError, context(), |
| 90 SmiConstant(MessageTemplate::kCalledNonCallable), callbackfn); | 247 SmiConstant(MessageTemplate::kCalledNonCallable), |
| 248 callbackfn()); | |
| 91 Unreachable(); | 249 Unreachable(); |
| 92 } | 250 } |
| 93 | 251 |
| 94 Bind(&done); | 252 Bind(&done); |
| 95 | 253 |
| 96 Node* a = generator(context, o, len); | |
| 97 | |
| 98 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. | 254 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. |
| 99 // [Already done by the arguments adapter] | 255 // [Already done by the arguments adapter] |
| 100 | 256 |
| 101 HandleFastElements(context, this_arg, o, len, callbackfn, processor, a, k, | 257 // 7. Let k be 0. |
| 102 &slow); | 258 // [Already done in code assembler initialization] |
| 103 | 259 |
| 104 // 7. Let k be 0. | 260 a_.Bind(generator(this)); |
| 105 // Already done above in initialization of the Variable k | 261 |
| 262 HandleFastElements(processor, action, &slow); | |
| 106 | 263 |
| 107 Bind(&slow); | 264 Bind(&slow); |
| 108 | 265 |
| 109 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, | 266 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
| 110 MachineType::TaggedPointer()); | 267 MachineType::TaggedPointer()); |
| 111 TailCallStub( | 268 TailCallStub( |
| 112 slow_case_continuation, context, target, new_target, | 269 slow_case_continuation, context(), target, new_target, |
| 113 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), | 270 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), |
| 114 receiver, callbackfn, this_arg, a, o, k.value(), len); | 271 receiver, callbackfn(), this_arg(), a_.value(), o(), k_.value(), len_); |
| 115 } | 272 } |
| 116 | 273 |
| 117 void GenerateIteratingArrayBuiltinLoopContinuation( | 274 void GenerateIteratingArrayBuiltinLoopContinuation( |
| 118 const BuiltinResultIndexInitializer& index_initializer, | 275 const BuiltinResultIndexInitializer& index_initializer, |
| 119 const CallResultProcessor& processor) { | 276 const CallResultProcessor& processor, const PostLoopAction& action) { |
| 120 // TODO(ishell): use constants from Descriptor once the JSFunction linkage | 277 // TODO(ishell): use constants from Descriptor once the JSFunction linkage |
| 121 // arguments are reordered. | 278 // arguments are reordered. |
| 122 Node* callbackfn = | 279 this_arg_ = |
| 280 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); | |
| 281 callbackfn_ = | |
| 123 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); | 282 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); |
| 124 Node* this_arg = | 283 a_.Bind(Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray)); |
| 125 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); | 284 k_.Bind( |
| 126 Node* a = | 285 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK)); |
| 127 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray); | 286 o_ = Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); |
| 128 Node* o = | 287 len_ = Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); |
| 129 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); | 288 context_ = |
| 130 Node* initial_k = | |
| 131 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK); | |
| 132 Node* len = | |
| 133 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); | |
| 134 Node* context = | |
| 135 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); | 289 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); |
| 136 | 290 |
| 137 index_initializer(context, a); | 291 index_initializer(this); |
| 138 | 292 |
| 139 // 8. Repeat, while k < len | 293 // 8. Repeat, while k < len |
| 140 Variable k(this, MachineRepresentation::kTagged, initial_k); | 294 Label loop(this, {&k_, &a_, &to_}); |
| 141 VariableList list({&k, &to_}, zone()); | |
| 142 Label loop(this, list); | |
| 143 Label after_loop(this); | 295 Label after_loop(this); |
| 144 Goto(&loop); | 296 Goto(&loop); |
| 145 Bind(&loop); | 297 Bind(&loop); |
| 146 { | 298 { |
| 147 GotoUnlessNumberLessThan(k.value(), len, &after_loop); | 299 GotoUnlessNumberLessThan(k(), len_, &after_loop); |
| 148 | 300 |
| 149 Label done_element(this, &to_); | 301 Label done_element(this, &to_); |
| 150 // a. Let Pk be ToString(k). | 302 // a. Let Pk be ToString(k). |
| 151 Node* p_k = ToString(context, k.value()); | 303 Node* p_k = ToString(context(), k()); |
| 152 | 304 |
| 153 // b. Let kPresent be HasProperty(O, Pk). | 305 // b. Let kPresent be HasProperty(O, Pk). |
| 154 // c. ReturnIfAbrupt(kPresent). | 306 // c. ReturnIfAbrupt(kPresent). |
| 155 Node* k_present = HasProperty(o, p_k, context); | 307 Node* k_present = HasProperty(o(), p_k, context()); |
| 156 | 308 |
| 157 // d. If kPresent is true, then | 309 // d. If kPresent is true, then |
| 158 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); | 310 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); |
| 159 | 311 |
| 160 // i. Let kValue be Get(O, Pk). | 312 // i. Let kValue be Get(O, Pk). |
| 161 // ii. ReturnIfAbrupt(kValue). | 313 // ii. ReturnIfAbrupt(kValue). |
| 162 Node* k_value = GetProperty(context, o, k.value()); | 314 Node* k_value = GetProperty(context(), o(), k()); |
| 163 | 315 |
| 164 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). | 316 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). |
| 165 // iv. ReturnIfAbrupt(funcResult). | 317 // iv. ReturnIfAbrupt(funcResult). |
| 166 Node* callback_result = | 318 a_.Bind(processor(this, k_value, k())); |
| 167 CallJS(CodeFactory::Call(isolate()), context, callbackfn, this_arg, | 319 Goto(&done_element); |
| 168 k_value, k.value(), o); | |
| 169 | 320 |
| 170 processor(context, k_value, a, callback_result); | |
| 171 Goto(&done_element); | |
| 172 Bind(&done_element); | 321 Bind(&done_element); |
| 173 | 322 |
| 174 // e. Increase k by 1. | 323 // e. Increase k by 1. |
| 175 k.Bind(NumberInc(k.value())); | 324 k_.Bind(NumberInc(k_.value())); |
| 176 Goto(&loop); | 325 Goto(&loop); |
| 177 } | 326 } |
| 178 Bind(&after_loop); | 327 Bind(&after_loop); |
| 179 Return(a); | |
| 180 } | |
| 181 | 328 |
| 182 Node* FilterResultGenerator(Node* context, Node* o, Node* len) { | 329 action(this); |
| 183 // 7. Let A be ArraySpeciesCreate(O, 0). | 330 Return(a_.value()); |
| 184 return ArraySpeciesCreate(context, o, SmiConstant(0)); | |
| 185 } | |
| 186 | |
| 187 void FilterResultIndexReinitializer(Node* context, Node* a) { | |
| 188 Variable merged_length(this, MachineRepresentation::kTagged); | |
| 189 Label has_length(this, &merged_length), not_js_array(this); | |
| 190 GotoIf(DoesntHaveInstanceType(a, JS_ARRAY_TYPE), ¬_js_array); | |
| 191 merged_length.Bind(LoadJSArrayLength(a)); | |
| 192 Goto(&has_length); | |
| 193 Bind(¬_js_array); | |
| 194 Node* len_property = | |
| 195 GetProperty(context, a, isolate()->factory()->length_string()); | |
| 196 merged_length.Bind( | |
| 197 CallStub(CodeFactory::ToLength(isolate()), context, len_property)); | |
| 198 Goto(&has_length); | |
| 199 Bind(&has_length); | |
| 200 Node* len = merged_length.value(); | |
| 201 | |
| 202 to_.Bind(len); | |
| 203 } | |
| 204 | |
| 205 void ForEachProcessor(Node* context, Node* value, Node* a, | |
| 206 Node* callback_result) {} | |
| 207 | |
| 208 void SomeProcessor(Node* context, Node* value, Node* a, | |
| 209 Node* callback_result) { | |
| 210 Label false_continue(this), return_true(this); | |
| 211 BranchIfToBooleanIsTrue(callback_result, &return_true, &false_continue); | |
| 212 Bind(&return_true); | |
| 213 Return(TrueConstant()); | |
| 214 Bind(&false_continue); | |
| 215 } | |
| 216 | |
| 217 void EveryProcessor(Node* context, Node* value, Node* a, | |
| 218 Node* callback_result) { | |
| 219 Label true_continue(this), return_false(this); | |
| 220 BranchIfToBooleanIsTrue(callback_result, &true_continue, &return_false); | |
| 221 Bind(&return_false); | |
| 222 Return(FalseConstant()); | |
| 223 Bind(&true_continue); | |
| 224 } | |
| 225 | |
| 226 void FilterProcessor(Node* context, Node* value, Node* a, | |
| 227 Node* callback_result) { | |
| 228 Label true_continue(this, &to_), false_continue(this); | |
| 229 BranchIfToBooleanIsTrue(callback_result, &true_continue, &false_continue); | |
| 230 Bind(&true_continue); | |
| 231 | |
| 232 // 1. let status be CreateDataPropertyOrThrow(A, ToString(to), kValue). | |
| 233 // 2. ReturnIfAbrupt(status) | |
| 234 Node* const p_to = ToString(context, to_.value()); | |
| 235 CallRuntime(Runtime::kCreateDataProperty, context, a, p_to, value); | |
| 236 | |
| 237 // 3. Increase to by 1. | |
| 238 to_.Bind(NumberInc(to_.value())); | |
| 239 Goto(&false_continue); | |
| 240 Bind(&false_continue); | |
| 241 } | 331 } |
| 242 | 332 |
| 243 private: | 333 private: |
| 244 Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind, | 334 void VisitAllFastElementsOneKind(ElementsKind kind, |
| 245 Node* this_arg, Node* o, Node* len, | 335 const CallResultProcessor& processor, |
| 246 Node* callbackfn, | 336 Label* array_changed, ParameterMode mode) { |
| 247 const CallResultProcessor& processor, | |
| 248 Node* a, Label* array_changed, | |
| 249 ParameterMode mode) { | |
| 250 Comment("begin VisitAllFastElementsOneKind"); | 337 Comment("begin VisitAllFastElementsOneKind"); |
| 251 Variable original_map(this, MachineRepresentation::kTagged); | 338 Variable original_map(this, MachineRepresentation::kTagged); |
| 252 original_map.Bind(LoadMap(o)); | 339 original_map.Bind(LoadMap(o())); |
| 253 VariableList list({&original_map, &to_}, zone()); | 340 VariableList list({&original_map, &a_, &k_, &to_}, zone()); |
| 254 Node* last_index = nullptr; | |
| 255 BuildFastLoop( | 341 BuildFastLoop( |
| 256 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode), | 342 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len(), mode), |
| 257 [=, &original_map, &last_index](Node* index) { | 343 [=, &original_map](Node* index) { |
| 258 last_index = index; | 344 k_.Bind(ParameterToTagged(index, mode)); |
| 259 Label one_element_done(this), hole_element(this); | 345 Label one_element_done(this), hole_element(this); |
| 260 | 346 |
| 261 // Check if o's map has changed during the callback. If so, we have to | 347 // Check if o's map has changed during the callback. If so, we have to |
| 262 // fall back to the slower spec implementation for the rest of the | 348 // fall back to the slower spec implementation for the rest of the |
| 263 // iteration. | 349 // iteration. |
| 264 Node* o_map = LoadMap(o); | 350 Node* o_map = LoadMap(o()); |
| 265 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); | 351 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); |
| 266 | 352 |
| 267 // Check if o's length has changed during the callback and if the | 353 // Check if o's length has changed during the callback and if the |
| 268 // index is now out of range of the new length. | 354 // index is now out of range of the new length. |
| 269 Node* tagged_index = ParameterToTagged(index, mode); | 355 GotoIf(SmiGreaterThanOrEqual(k_.value(), LoadJSArrayLength(o())), |
| 270 GotoIf(SmiGreaterThanOrEqual(tagged_index, LoadJSArrayLength(o)), | |
| 271 array_changed); | 356 array_changed); |
| 272 | 357 |
| 273 // Re-load the elements array. If may have been resized. | 358 // Re-load the elements array. If may have been resized. |
| 274 Node* elements = LoadElements(o); | 359 Node* elements = LoadElements(o()); |
| 275 | 360 |
| 276 // Fast case: load the element directly from the elements FixedArray | 361 // Fast case: load the element directly from the elements FixedArray |
| 277 // and call the callback if the element is not the hole. | 362 // and call the callback if the element is not the hole. |
| 278 DCHECK(kind == FAST_ELEMENTS || kind == FAST_DOUBLE_ELEMENTS); | 363 DCHECK(kind == FAST_ELEMENTS || kind == FAST_DOUBLE_ELEMENTS); |
| 279 int base_size = kind == FAST_ELEMENTS | 364 int base_size = kind == FAST_ELEMENTS |
| 280 ? FixedArray::kHeaderSize | 365 ? FixedArray::kHeaderSize |
| 281 : (FixedArray::kHeaderSize - kHeapObjectTag); | 366 : (FixedArray::kHeaderSize - kHeapObjectTag); |
| 282 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); | 367 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); |
| 283 Node* value = nullptr; | 368 Node* value = nullptr; |
| 284 if (kind == FAST_ELEMENTS) { | 369 if (kind == FAST_ELEMENTS) { |
| 285 value = LoadObjectField(elements, offset); | 370 value = LoadObjectField(elements, offset); |
| 286 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); | 371 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); |
| 287 } else { | 372 } else { |
| 288 Node* double_value = | 373 Node* double_value = |
| 289 LoadDoubleWithHoleCheck(elements, offset, &hole_element); | 374 LoadDoubleWithHoleCheck(elements, offset, &hole_element); |
| 290 value = AllocateHeapNumberWithValue(double_value); | 375 value = AllocateHeapNumberWithValue(double_value); |
| 291 } | 376 } |
| 292 Node* callback_result = | 377 a_.Bind(processor(this, value, k())); |
| 293 CallJS(CodeFactory::Call(isolate()), context, callbackfn, | |
| 294 this_arg, value, tagged_index, o); | |
| 295 processor(context, value, a, callback_result); | |
| 296 Goto(&one_element_done); | 378 Goto(&one_element_done); |
| 297 | 379 |
| 298 Bind(&hole_element); | 380 Bind(&hole_element); |
| 299 // Check if o's prototype change unexpectedly has elements after the | 381 // Check if o's prototype change unexpectedly has elements after the |
| 300 // callback in the case of a hole. | 382 // callback in the case of a hole. |
| 301 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, | 383 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, |
| 302 array_changed); | 384 array_changed); |
| 303 | 385 |
| 304 Bind(&one_element_done); | 386 Bind(&one_element_done); |
| 305 }, | 387 }, |
| 306 1, mode, IndexAdvanceMode::kPost); | 388 1, mode, IndexAdvanceMode::kPost); |
| 307 Comment("end VisitAllFastElementsOneKind"); | 389 Comment("end VisitAllFastElementsOneKind"); |
| 308 return last_index; | |
| 309 } | 390 } |
| 310 | 391 |
| 311 void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len, | 392 void HandleFastElements(const CallResultProcessor& processor, |
| 312 Node* callbackfn, CallResultProcessor processor, | 393 const PostLoopAction& action, Label* slow) { |
| 313 Node* a, Variable& k, Label* slow) { | |
| 314 Label switch_on_elements_kind(this), fast_elements(this), | 394 Label switch_on_elements_kind(this), fast_elements(this), |
| 315 maybe_double_elements(this), fast_double_elements(this); | 395 maybe_double_elements(this), fast_double_elements(this); |
| 316 | 396 |
| 317 Comment("begin HandleFastElements"); | 397 Comment("begin HandleFastElements"); |
| 318 // Non-smi lengths must use the slow path. | 398 // Non-smi lengths must use the slow path. |
| 319 GotoIf(TaggedIsNotSmi(len), slow); | 399 GotoIf(TaggedIsNotSmi(len()), slow); |
| 320 | 400 |
| 321 BranchIfFastJSArray(o, context, | 401 BranchIfFastJSArray(o(), context(), |
| 322 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | 402 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, |
| 323 &switch_on_elements_kind, slow); | 403 &switch_on_elements_kind, slow); |
| 324 | 404 |
| 325 Bind(&switch_on_elements_kind); | 405 Bind(&switch_on_elements_kind); |
| 326 // Select by ElementsKind | 406 // Select by ElementsKind |
| 327 Node* o_map = LoadMap(o); | 407 Node* o_map = LoadMap(o()); |
| 328 Node* bit_field2 = LoadMapBitField2(o_map); | 408 Node* bit_field2 = LoadMapBitField2(o_map); |
| 329 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 409 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| 330 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), | 410 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
| 331 &maybe_double_elements, &fast_elements); | 411 &maybe_double_elements, &fast_elements); |
| 332 | 412 |
| 333 ParameterMode mode = OptimalParameterMode(); | 413 ParameterMode mode = OptimalParameterMode(); |
| 334 Bind(&fast_elements); | 414 Bind(&fast_elements); |
| 335 { | 415 { |
| 336 Label array_changed(this, Label::kDeferred); | 416 VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode); |
| 337 Node* last_index = VisitAllFastElementsOneKind( | 417 |
| 338 context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a, | 418 action(this); |
| 339 &array_changed, mode); | |
| 340 | 419 |
| 341 // No exception, return success | 420 // No exception, return success |
| 342 Return(a); | 421 Return(a_.value()); |
| 343 | |
| 344 Bind(&array_changed); | |
| 345 k.Bind(ParameterToTagged(last_index, mode)); | |
| 346 Goto(slow); | |
| 347 } | 422 } |
| 348 | 423 |
| 349 Bind(&maybe_double_elements); | 424 Bind(&maybe_double_elements); |
| 350 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), | 425 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), |
| 351 slow, &fast_double_elements); | 426 slow, &fast_double_elements); |
| 352 | 427 |
| 353 Bind(&fast_double_elements); | 428 Bind(&fast_double_elements); |
| 354 { | 429 { |
| 355 Label array_changed(this, Label::kDeferred); | 430 VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode); |
| 356 Node* last_index = VisitAllFastElementsOneKind( | 431 |
| 357 context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn, | 432 action(this); |
| 358 processor, a, &array_changed, mode); | |
| 359 | 433 |
| 360 // No exception, return success | 434 // No exception, return success |
| 361 Return(a); | 435 Return(a_.value()); |
| 362 | |
| 363 Bind(&array_changed); | |
| 364 k.Bind(ParameterToTagged(last_index, mode)); | |
| 365 Goto(slow); | |
| 366 } | 436 } |
| 367 } | 437 } |
| 368 | 438 |
| 439 Node* callbackfn_; | |
| 440 Node* o_; | |
| 441 Node* this_arg_; | |
| 442 Node* len_; | |
| 443 Node* context_; | |
| 444 Variable k_; | |
| 445 Variable a_; | |
| 369 Variable to_; | 446 Variable to_; |
| 370 }; | 447 }; |
| 371 | 448 |
| 372 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { | 449 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
| 373 Variable arg_index(this, MachineType::PointerRepresentation()); | 450 Variable arg_index(this, MachineType::PointerRepresentation()); |
| 374 Label default_label(this, &arg_index); | 451 Label default_label(this, &arg_index); |
| 375 Label smi_transition(this); | 452 Label smi_transition(this); |
| 376 Label object_push_pre(this); | 453 Label object_push_pre(this); |
| 377 Label object_push(this, &arg_index); | 454 Label object_push(this, &arg_index); |
| 378 Label double_push(this, &arg_index); | 455 Label double_push(this, &arg_index); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 { | 597 { |
| 521 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, | 598 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
| 522 MachineType::TaggedPointer()); | 599 MachineType::TaggedPointer()); |
| 523 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, | 600 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, |
| 524 argc); | 601 argc); |
| 525 } | 602 } |
| 526 } | 603 } |
| 527 | 604 |
| 528 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 605 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 529 GenerateIteratingArrayBuiltinLoopContinuation( | 606 GenerateIteratingArrayBuiltinLoopContinuation( |
| 530 [](Node* context, Node* a) {}, | 607 &ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer, |
| 531 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 608 &ArrayBuiltinCodeStubAssembler::ForEachProcessor, |
| 532 ForEachProcessor(context, value, a, callback_result); | 609 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 533 }); | |
| 534 } | |
| 535 | |
| 536 TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) { | |
| 537 GenerateIteratingArrayBuiltinBody( | |
| 538 "Array.prototype.filter", | |
| 539 [=](Node* context, Node* o, Node* len) { | |
| 540 return FilterResultGenerator(context, o, len); | |
| 541 }, | |
| 542 [this](Node* context, Node* value, Node* a, Node* callback_result) { | |
| 543 FilterProcessor(context, value, a, callback_result); | |
| 544 }, | |
| 545 CodeFactory::ArrayFilterLoopContinuation(isolate())); | |
| 546 } | |
| 547 | |
| 548 TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) { | |
| 549 GenerateIteratingArrayBuiltinLoopContinuation( | |
| 550 [this](Node* context, Node* a) { | |
| 551 FilterResultIndexReinitializer(context, a); | |
| 552 }, | |
| 553 [this](Node* context, Node* value, Node* a, Node* callback_result) { | |
| 554 FilterProcessor(context, value, a, callback_result); | |
| 555 }); | |
| 556 } | 610 } |
| 557 | 611 |
| 558 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { | 612 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { |
| 559 GenerateIteratingArrayBuiltinBody( | 613 GenerateIteratingArrayBuiltinBody( |
| 560 "Array.prototype.forEach", | 614 "Array.prototype.forEach", |
| 561 [=](Node*, Node*, Node*) { return UndefinedConstant(); }, | 615 &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator, |
| 562 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 616 &ArrayBuiltinCodeStubAssembler::ForEachProcessor, |
| 563 ForEachProcessor(context, value, a, callback_result); | 617 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, |
| 564 }, | |
| 565 CodeFactory::ArrayForEachLoopContinuation(isolate())); | 618 CodeFactory::ArrayForEachLoopContinuation(isolate())); |
|
Igor Sheludko
2017/03/21 14:20:28
FYI: We have a Builtins::CallableFor(), so there's
danno
2017/03/21 15:55:29
To land quickly, will do this in a follow-on CL.
| |
| 566 } | 619 } |
| 567 | 620 |
| 568 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 621 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 569 GenerateIteratingArrayBuiltinLoopContinuation( | 622 GenerateIteratingArrayBuiltinLoopContinuation( |
| 570 [](Node* context, Node* a) {}, | 623 &ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer, |
| 571 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 624 &ArrayBuiltinCodeStubAssembler::SomeProcessor, |
| 572 SomeProcessor(context, value, a, callback_result); | 625 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 573 }); | |
| 574 } | 626 } |
| 575 | 627 |
| 576 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { | 628 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { |
| 577 GenerateIteratingArrayBuiltinBody( | 629 GenerateIteratingArrayBuiltinBody( |
| 578 "Array.prototype.some", | 630 "Array.prototype.some", |
| 579 [=](Node*, Node*, Node*) { return FalseConstant(); }, | 631 &ArrayBuiltinCodeStubAssembler::SomeResultGenerator, |
| 580 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 632 &ArrayBuiltinCodeStubAssembler::SomeProcessor, |
| 581 SomeProcessor(context, value, a, callback_result); | 633 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, |
| 582 }, | |
| 583 CodeFactory::ArraySomeLoopContinuation(isolate())); | 634 CodeFactory::ArraySomeLoopContinuation(isolate())); |
| 584 } | 635 } |
| 585 | 636 |
| 586 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 637 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 587 GenerateIteratingArrayBuiltinLoopContinuation( | 638 GenerateIteratingArrayBuiltinLoopContinuation( |
| 588 [](Node* context, Node* a) {}, | 639 &ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer, |
| 589 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 640 &ArrayBuiltinCodeStubAssembler::EveryProcessor, |
| 590 EveryProcessor(context, value, a, callback_result); | 641 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 591 }); | |
| 592 } | 642 } |
| 593 | 643 |
| 594 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { | 644 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { |
| 595 GenerateIteratingArrayBuiltinBody( | 645 GenerateIteratingArrayBuiltinBody( |
| 596 "Array.prototype.every", | 646 "Array.prototype.every", |
| 597 [=](Node*, Node*, Node*) { return TrueConstant(); }, | 647 &ArrayBuiltinCodeStubAssembler::EveryResultGenerator, |
| 598 [this](Node* context, Node* value, Node* a, Node* callback_result) { | 648 &ArrayBuiltinCodeStubAssembler::EveryProcessor, |
| 599 EveryProcessor(context, value, a, callback_result); | 649 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, |
| 600 }, | |
| 601 CodeFactory::ArrayEveryLoopContinuation(isolate())); | 650 CodeFactory::ArrayEveryLoopContinuation(isolate())); |
| 602 } | 651 } |
| 603 | 652 |
| 653 TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) { | |
| 654 GenerateIteratingArrayBuiltinLoopContinuation( | |
| 655 &ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer, | |
| 656 &ArrayBuiltinCodeStubAssembler::ReduceProcessor, | |
| 657 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction); | |
| 658 } | |
| 659 | |
| 660 TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) { | |
| 661 GenerateIteratingArrayBuiltinBody( | |
| 662 "Array.prototype.reduce", | |
| 663 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator, | |
| 664 &ArrayBuiltinCodeStubAssembler::ReduceProcessor, | |
| 665 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction, | |
| 666 CodeFactory::ArrayReduceLoopContinuation(isolate())); | |
| 667 } | |
| 668 | |
| 669 TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) { | |
| 670 GenerateIteratingArrayBuiltinLoopContinuation( | |
| 671 &ArrayBuiltinCodeStubAssembler::FilterResultIndexReinitializer, | |
| 672 &ArrayBuiltinCodeStubAssembler::FilterProcessor, | |
| 673 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); | |
| 674 } | |
| 675 | |
| 676 TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) { | |
| 677 GenerateIteratingArrayBuiltinBody( | |
| 678 "Array.prototype.reduce", | |
| 679 &ArrayBuiltinCodeStubAssembler::FilterResultGenerator, | |
| 680 &ArrayBuiltinCodeStubAssembler::FilterProcessor, | |
| 681 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, | |
| 682 CodeFactory::ArrayFilterLoopContinuation(isolate())); | |
| 683 } | |
| 684 | |
| 604 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { | 685 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
| 605 Node* object = Parameter(Descriptor::kArg); | 686 Node* object = Parameter(Descriptor::kArg); |
| 606 Node* context = Parameter(Descriptor::kContext); | 687 Node* context = Parameter(Descriptor::kContext); |
| 607 | 688 |
| 608 Label call_runtime(this), return_true(this), return_false(this); | 689 Label call_runtime(this), return_true(this), return_false(this); |
| 609 | 690 |
| 610 GotoIf(TaggedIsSmi(object), &return_false); | 691 GotoIf(TaggedIsSmi(object), &return_false); |
| 611 Node* instance_type = LoadInstanceType(object); | 692 Node* instance_type = LoadInstanceType(object); |
| 612 | 693 |
| 613 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), | 694 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), |
| (...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1655 { | 1736 { |
| 1656 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); | 1737 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); |
| 1657 CallRuntime(Runtime::kThrowTypeError, context, message, | 1738 CallRuntime(Runtime::kThrowTypeError, context, message, |
| 1658 HeapConstant(operation)); | 1739 HeapConstant(operation)); |
| 1659 Unreachable(); | 1740 Unreachable(); |
| 1660 } | 1741 } |
| 1661 } | 1742 } |
| 1662 | 1743 |
| 1663 } // namespace internal | 1744 } // namespace internal |
| 1664 } // namespace v8 | 1745 } // namespace v8 |
| OLD | NEW |