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) {} | 15 : CodeStubAssembler(state) {} |
| 16 | 16 |
| 17 typedef std::function<Node*(Node* o, Node* len)> BuiltinResultGenerator; | 17 typedef std::function<std::pair<Node*, Node*>( |
|
danno
2017/03/17 10:26:31
Per Camillo's comments, I am going to add comments
| |
| 18 typedef std::function<void(Node* a, Node* pK, Node* value)> | 18 ArrayBuiltinCodeStubAssembler* masm, Node* this_arg, Node* o, Node* len)> |
| 19 BuiltinResultGenerator; | |
| 20 | |
| 21 typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm, | |
| 22 Node* context, Node* callbackfn, Node* this_arg, | |
| 23 Node* k_value, Node* k, Node* o, Node* a)> | |
| 19 CallResultProcessor; | 24 CallResultProcessor; |
| 20 | 25 |
| 26 typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm, Node* context, | |
| 27 Node* a)> | |
| 28 PostLoopAction; | |
| 29 | |
| 21 void GenerateIteratingArrayBuiltinBody( | 30 void GenerateIteratingArrayBuiltinBody( |
| 22 const char* name, const BuiltinResultGenerator& generator, | 31 const char* name, const BuiltinResultGenerator& generator, |
| 23 const CallResultProcessor& processor, | 32 const CallResultProcessor& processor, const PostLoopAction& action, |
| 24 const Callable& slow_case_continuation) { | 33 const Callable& slow_case_continuation) { |
| 25 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); | 34 Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); |
| 26 Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback); | 35 Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback); |
| 27 Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); | 36 Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); |
| 28 Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext); | 37 Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext); |
| 29 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); | 38 Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); |
| 30 | 39 |
| 31 Variable k(this, MachineRepresentation::kTagged, SmiConstant(0)); | 40 Variable k(this, MachineRepresentation::kTagged, SmiConstant(0)); |
| 32 Label non_array(this), slow(this, &k), array_changes(this, &k); | 41 Variable a(this, MachineRepresentation::kTagged, UndefinedConstant()); |
| 42 Label non_array(this), slow(this, {&k, &a}), array_changes(this, {&k, &a}); | |
| 33 | 43 |
| 34 // TODO(danno): Seriously? Do we really need to throw the exact error | 44 // TODO(danno): Seriously? Do we really need to throw the exact error |
| 35 // message on null and undefined so that the webkit tests pass? | 45 // message on null and undefined so that the webkit tests pass? |
| 36 Label throw_null_undefined_exception(this, Label::kDeferred); | 46 Label throw_null_undefined_exception(this, Label::kDeferred); |
| 37 GotoIf(WordEqual(receiver, NullConstant()), | 47 GotoIf(WordEqual(receiver, NullConstant()), |
| 38 &throw_null_undefined_exception); | 48 &throw_null_undefined_exception); |
| 39 GotoIf(WordEqual(receiver, UndefinedConstant()), | 49 GotoIf(WordEqual(receiver, UndefinedConstant()), |
| 40 &throw_null_undefined_exception); | 50 &throw_null_undefined_exception); |
| 41 | 51 |
| 42 // By the book: taken directly from the ECMAScript 2015 specification | 52 // By the book: taken directly from the ECMAScript 2015 specification |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 | 88 |
| 79 Bind(&type_exception); | 89 Bind(&type_exception); |
| 80 { | 90 { |
| 81 CallRuntime(Runtime::kThrowTypeError, context, | 91 CallRuntime(Runtime::kThrowTypeError, context, |
| 82 SmiConstant(MessageTemplate::kCalledNonCallable), callbackfn); | 92 SmiConstant(MessageTemplate::kCalledNonCallable), callbackfn); |
| 83 Unreachable(); | 93 Unreachable(); |
| 84 } | 94 } |
| 85 | 95 |
| 86 Bind(&done); | 96 Bind(&done); |
| 87 | 97 |
| 88 Node* a = generator(o, len); | 98 Node* initial_a; |
| 99 Node* initial_k; | |
| 100 std::tie(initial_a, initial_k) = generator(this, this_arg, o, len); | |
| 89 | 101 |
| 90 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. | 102 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. |
| 91 // [Already done by the arguments adapter] | 103 // [Already done by the arguments adapter] |
| 92 | 104 |
| 93 HandleFastElements(context, this_arg, o, len, callbackfn, processor, a, k, | 105 // 7. Let k be 0. |
| 94 &slow); | 106 k.Bind(initial_k); |
| 107 a.Bind(initial_a); | |
| 95 | 108 |
| 96 // 7. Let k be 0. | 109 HandleFastElements(context, this_arg, o, len, callbackfn, processor, action, |
| 97 // Already done above in initialization of the Variable k | 110 a, k, &slow); |
| 98 | 111 |
| 99 Bind(&slow); | 112 Bind(&slow); |
| 100 | 113 |
| 101 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, | 114 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
| 102 MachineType::TaggedPointer()); | 115 MachineType::TaggedPointer()); |
| 103 TailCallStub( | 116 TailCallStub( |
| 104 slow_case_continuation, context, target, new_target, | 117 slow_case_continuation, context, target, new_target, |
| 105 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), | 118 Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), |
| 106 receiver, callbackfn, this_arg, a, o, k.value(), len); | 119 receiver, callbackfn, this_arg, a.value(), o, k.value(), len); |
| 107 } | 120 } |
| 108 | 121 |
| 109 void GenerateIteratingArrayBuiltinLoopContinuation( | 122 void GenerateIteratingArrayBuiltinLoopContinuation( |
| 110 const CallResultProcessor& processor) { | 123 const CallResultProcessor& processor, const PostLoopAction& action) { |
| 111 Node* callbackfn = | 124 Node* callbackfn = |
| 112 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); | 125 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); |
| 113 Node* this_arg = | 126 Node* this_arg = |
| 114 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); | 127 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); |
| 115 Node* a = | 128 Node* initial_a = |
| 116 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray); | 129 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray); |
| 117 Node* o = | 130 Node* o = |
| 118 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); | 131 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); |
| 119 Node* initial_k = | 132 Node* initial_k = |
| 120 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK); | 133 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK); |
| 121 Node* len = | 134 Node* len = |
| 122 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); | 135 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); |
| 123 Node* context = | 136 Node* context = |
| 124 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); | 137 Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); |
| 125 | 138 |
| 126 // 8. Repeat, while k < len | 139 // 8. Repeat, while k < len |
| 127 Variable k(this, MachineRepresentation::kTagged, initial_k); | 140 Variable k(this, MachineRepresentation::kTagged, initial_k); |
| 128 Label loop(this, &k); | 141 Variable a(this, MachineRepresentation::kTagged, initial_a); |
| 142 Label loop(this, {&k, &a}); | |
| 129 Label after_loop(this); | 143 Label after_loop(this); |
| 130 Goto(&loop); | 144 Goto(&loop); |
| 131 Bind(&loop); | 145 Bind(&loop); |
| 132 { | 146 { |
| 133 GotoUnlessNumberLessThan(k.value(), len, &after_loop); | 147 GotoUnlessNumberLessThan(k.value(), len, &after_loop); |
| 134 | 148 |
| 135 Label done_element(this); | 149 Label done_element(this); |
| 136 // a. Let Pk be ToString(k). | 150 // a. Let Pk be ToString(k). |
| 137 Node* p_k = ToString(context, k.value()); | 151 Node* p_k = ToString(context, k.value()); |
| 138 | 152 |
| 139 // b. Let kPresent be HasProperty(O, Pk). | 153 // b. Let kPresent be HasProperty(O, Pk). |
| 140 // c. ReturnIfAbrupt(kPresent). | 154 // c. ReturnIfAbrupt(kPresent). |
| 141 Node* k_present = HasProperty(o, p_k, context); | 155 Node* k_present = HasProperty(o, p_k, context); |
| 142 | 156 |
| 143 // d. If kPresent is true, then | 157 // d. If kPresent is true, then |
| 144 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); | 158 GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); |
| 145 | 159 |
| 146 // i. Let kValue be Get(O, Pk). | 160 // i. Let kValue be Get(O, Pk). |
| 147 // ii. ReturnIfAbrupt(kValue). | 161 // ii. ReturnIfAbrupt(kValue). |
| 148 Node* k_value = GetProperty(context, o, k.value()); | 162 Node* k_value = GetProperty(context, o, k.value()); |
| 149 | 163 |
| 150 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). | 164 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). |
| 151 // iv. ReturnIfAbrupt(funcResult). | 165 // iv. ReturnIfAbrupt(funcResult). |
| 152 Node* result = CallJS(CodeFactory::Call(isolate()), context, callbackfn, | 166 a.Bind(processor(this, context, callbackfn, this_arg, k_value, k.value(), |
| 153 this_arg, k_value, k.value(), o); | 167 o, a.value())); |
| 154 | |
| 155 processor(a, p_k, result); | |
| 156 Goto(&done_element); | 168 Goto(&done_element); |
| 157 Bind(&done_element); | 169 Bind(&done_element); |
| 158 | 170 |
| 159 // e. Increase k by 1. | 171 // e. Increase k by 1. |
| 160 k.Bind(NumberInc(k.value())); | 172 k.Bind(NumberInc(k.value())); |
| 161 Goto(&loop); | 173 Goto(&loop); |
| 162 } | 174 } |
| 163 Bind(&after_loop); | 175 Bind(&after_loop); |
| 164 Return(a); | 176 |
| 177 action(this, context, a.value()); | |
| 178 | |
| 179 Return(a.value()); | |
| 165 } | 180 } |
| 166 | 181 |
| 167 void ForEachProcessor(Node* a, Node* p_k, Node* value) {} | 182 std::pair<Node*, Node*> ForEachResultGenerator(Node* this_arg, Node* o, |
| 183 Node* len) { | |
| 184 return std::make_pair(UndefinedConstant(), SmiConstant(0)); | |
| 185 } | |
| 168 | 186 |
| 169 void SomeProcessor(Node* a, Node* p_k, Node* value) { | 187 Node* ForEachProcessor(Node* context, Node* callbackfn, Node* this_arg, |
| 188 Node* k_value, Node* k, Node* o, Node* a) { | |
| 189 CallJS(CodeFactory::Call(isolate()), context, callbackfn, this_arg, k_value, | |
| 190 k, o); | |
| 191 return a; | |
| 192 } | |
| 193 | |
| 194 std::pair<Node*, Node*> SomeResultGenerator(Node* this_arg, Node* o, | |
| 195 Node* len) { | |
| 196 return std::make_pair(FalseConstant(), SmiConstant(0)); | |
| 197 } | |
| 198 | |
| 199 Node* SomeProcessor(Node* context, Node* callbackfn, Node* this_arg, | |
| 200 Node* k_value, Node* k, Node* o, Node* a) { | |
| 201 Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn, | |
| 202 this_arg, k_value, k, o); | |
| 170 Label false_continue(this), return_true(this); | 203 Label false_continue(this), return_true(this); |
| 171 BranchIfToBooleanIsTrue(value, &return_true, &false_continue); | 204 BranchIfToBooleanIsTrue(value, &return_true, &false_continue); |
| 172 Bind(&return_true); | 205 Bind(&return_true); |
| 173 Return(TrueConstant()); | 206 Return(TrueConstant()); |
| 174 Bind(&false_continue); | 207 Bind(&false_continue); |
| 208 return a; | |
| 175 } | 209 } |
| 176 | 210 |
| 177 void EveryProcessor(Node* a, Node* p_k, Node* value) { | 211 std::pair<Node*, Node*> EveryResultGenerator(Node* this_arg, Node* o, |
| 212 Node* len) { | |
| 213 return std::make_pair(TrueConstant(), SmiConstant(0)); | |
| 214 } | |
| 215 | |
| 216 Node* EveryProcessor(Node* context, Node* callbackfn, Node* this_arg, | |
| 217 Node* k_value, Node* k, Node* o, Node* a) { | |
| 218 Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn, | |
| 219 this_arg, k_value, k, o); | |
| 178 Label true_continue(this), return_false(this); | 220 Label true_continue(this), return_false(this); |
| 179 BranchIfToBooleanIsTrue(value, &true_continue, &return_false); | 221 BranchIfToBooleanIsTrue(value, &true_continue, &return_false); |
| 180 Bind(&return_false); | 222 Bind(&return_false); |
| 181 Return(FalseConstant()); | 223 Return(FalseConstant()); |
| 182 Bind(&true_continue); | 224 Bind(&true_continue); |
| 225 return a; | |
| 183 } | 226 } |
| 184 | 227 |
| 228 std::pair<Node*, Node*> ReduceResultGenerator(Node* initial_value, Node* o, | |
| 229 Node* len) { | |
| 230 Variable a(this, MachineRepresentation::kTagged, UndefinedConstant()); | |
| 231 Label no_initial_value(this), has_initial_value(this), done(this, {&a}); | |
| 232 | |
| 233 // 8. If initialValue is present, then | |
| 234 Node* parent_frame_ptr = LoadParentFramePointer(); | |
| 235 Node* marker_or_function = LoadBufferObject( | |
| 236 parent_frame_ptr, CommonFrameConstants::kContextOrFrameTypeOffset); | |
| 237 GotoIf( | |
| 238 MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR), | |
| 239 &has_initial_value); | |
| 240 | |
| 241 // Has arguments adapter, check count. | |
| 242 Node* adapted_parameter_count = LoadBufferObject( | |
| 243 parent_frame_ptr, ArgumentsAdaptorFrameConstants::kLengthOffset); | |
| 244 Branch(SmiLessThan(adapted_parameter_count, | |
| 245 SmiConstant(IteratingArrayBuiltinDescriptor::kThisArg)), | |
| 246 &no_initial_value, &has_initial_value); | |
| 247 | |
| 248 // a. Set accumulator to initialValue. | |
| 249 Bind(&has_initial_value); | |
| 250 a.Bind(initial_value); | |
| 251 Goto(&done); | |
| 252 | |
| 253 // 9. Else initialValue is not present, | |
| 254 Bind(&no_initial_value); | |
| 255 | |
| 256 // a. Let kPresent be false. | |
| 257 a.Bind(TheHoleConstant()); | |
| 258 Goto(&done); | |
| 259 Bind(&done); | |
| 260 return std::make_pair(a.value(), SmiConstant(0)); | |
| 261 } | |
| 262 | |
| 263 Node* ReduceProcessor(Node* context, Node* callbackfn, Node* this_arg, | |
| 264 Node* k_value, Node* k, Node* o, Node* a) { | |
| 265 Variable result(this, MachineRepresentation::kTagged); | |
| 266 Label done(this, {&result}), initial(this); | |
| 267 GotoIf(WordEqual(a, TheHoleConstant()), &initial); | |
| 268 result.Bind(CallJS(CodeFactory::Call(isolate()), context, callbackfn, | |
| 269 UndefinedConstant(), a, k_value, k, o)); | |
| 270 Goto(&done); | |
| 271 | |
| 272 Bind(&initial); | |
| 273 result.Bind(k_value); | |
| 274 Goto(&done); | |
| 275 | |
| 276 Bind(&done); | |
| 277 return result.value(); | |
| 278 } | |
| 279 | |
| 280 void ReducePostLoopAction(Node* context, Node* a) { | |
| 281 Label ok(this); | |
| 282 GotoIf(WordNotEqual(a, TheHoleConstant()), &ok); | |
| 283 CallRuntime(Runtime::kThrowTypeError, context, | |
| 284 SmiConstant(MessageTemplate::kReduceNoInitial)); | |
| 285 Unreachable(); | |
| 286 Bind(&ok); | |
| 287 } | |
| 288 | |
| 289 void NullPostLoopAction(Node* context, Node* a) {} | |
| 290 | |
| 185 private: | 291 private: |
| 186 Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind, | 292 Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind, |
| 187 Node* this_arg, Node* o, Node* len, | 293 Node* this_arg, Node* o, Node* len, |
| 188 Node* callbackfn, | 294 Node* callbackfn, |
| 189 const CallResultProcessor& processor, | 295 const CallResultProcessor& processor, |
| 190 Node* a, Label* array_changed, | 296 Variable& a, Label* array_changed, |
| 191 ParameterMode mode) { | 297 ParameterMode mode) { |
| 192 Comment("begin VisitAllFastElementsOneKind"); | 298 Comment("begin VisitAllFastElementsOneKind"); |
| 193 Variable original_map(this, MachineRepresentation::kTagged); | 299 Variable original_map(this, MachineRepresentation::kTagged); |
| 194 original_map.Bind(LoadMap(o)); | 300 original_map.Bind(LoadMap(o)); |
| 195 VariableList list({&original_map}, zone()); | 301 VariableList list({&original_map, &a}, zone()); |
| 196 Node* last_index = nullptr; | 302 Node* last_index = nullptr; |
| 197 BuildFastLoop( | 303 BuildFastLoop( |
| 198 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode), | 304 list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode), |
| 199 [=, &original_map, &last_index](Node* index) { | 305 [=, &a, &original_map, &last_index](Node* index) { |
| 200 last_index = index; | 306 last_index = index; |
| 201 Label one_element_done(this), hole_element(this); | 307 Label one_element_done(this), hole_element(this); |
| 202 | 308 |
| 203 // Check if o's map has changed during the callback. If so, we have to | 309 // Check if o's map has changed during the callback. If so, we have to |
| 204 // fall back to the slower spec implementation for the rest of the | 310 // fall back to the slower spec implementation for the rest of the |
| 205 // iteration. | 311 // iteration. |
| 206 Node* o_map = LoadMap(o); | 312 Node* o_map = LoadMap(o); |
| 207 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); | 313 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed); |
| 208 | 314 |
| 209 // Check if o's length has changed during the callback and if the | 315 // Check if o's length has changed during the callback and if the |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 224 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); | 330 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size); |
| 225 Node* value = nullptr; | 331 Node* value = nullptr; |
| 226 if (kind == FAST_ELEMENTS) { | 332 if (kind == FAST_ELEMENTS) { |
| 227 value = LoadObjectField(elements, offset); | 333 value = LoadObjectField(elements, offset); |
| 228 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); | 334 GotoIf(WordEqual(value, TheHoleConstant()), &hole_element); |
| 229 } else { | 335 } else { |
| 230 Node* double_value = | 336 Node* double_value = |
| 231 LoadDoubleWithHoleCheck(elements, offset, &hole_element); | 337 LoadDoubleWithHoleCheck(elements, offset, &hole_element); |
| 232 value = AllocateHeapNumberWithValue(double_value); | 338 value = AllocateHeapNumberWithValue(double_value); |
| 233 } | 339 } |
| 234 Node* result = CallJS(CodeFactory::Call(isolate()), context, | 340 a.Bind(processor(this, context, callbackfn, this_arg, value, |
| 235 callbackfn, this_arg, value, tagged_index, o); | 341 tagged_index, o, a.value())); |
| 236 processor(a, tagged_index, result); | |
| 237 Goto(&one_element_done); | 342 Goto(&one_element_done); |
| 238 | 343 |
| 239 Bind(&hole_element); | 344 Bind(&hole_element); |
| 240 // Check if o's prototype change unexpectedly has elements after the | 345 // Check if o's prototype change unexpectedly has elements after the |
| 241 // callback in the case of a hole. | 346 // callback in the case of a hole. |
| 242 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, | 347 BranchIfPrototypesHaveNoElements(o_map, &one_element_done, |
| 243 array_changed); | 348 array_changed); |
| 244 | 349 |
| 245 Bind(&one_element_done); | 350 Bind(&one_element_done); |
| 246 }, | 351 }, |
| 247 1, mode, IndexAdvanceMode::kPost); | 352 1, mode, IndexAdvanceMode::kPost); |
| 248 Comment("end VisitAllFastElementsOneKind"); | 353 Comment("end VisitAllFastElementsOneKind"); |
| 249 return last_index; | 354 return last_index; |
| 250 } | 355 } |
| 251 | 356 |
| 252 void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len, | 357 void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len, |
| 253 Node* callbackfn, CallResultProcessor processor, | 358 Node* callbackfn, |
| 254 Node* a, Variable& k, Label* slow) { | 359 const CallResultProcessor& processor, |
| 360 const PostLoopAction& action, Variable& a, | |
| 361 Variable& k, Label* slow) { | |
| 255 Label switch_on_elements_kind(this), fast_elements(this), | 362 Label switch_on_elements_kind(this), fast_elements(this), |
| 256 maybe_double_elements(this), fast_double_elements(this); | 363 maybe_double_elements(this), fast_double_elements(this); |
| 257 | 364 |
| 258 Comment("begin HandleFastElements"); | 365 Comment("begin HandleFastElements"); |
| 259 // Non-smi lengths must use the slow path. | 366 // Non-smi lengths must use the slow path. |
| 260 GotoIf(TaggedIsNotSmi(len), slow); | 367 GotoIf(TaggedIsNotSmi(len), slow); |
| 261 | 368 |
| 262 BranchIfFastJSArray(o, context, | 369 BranchIfFastJSArray(o, context, |
| 263 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | 370 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, |
| 264 &switch_on_elements_kind, slow); | 371 &switch_on_elements_kind, slow); |
| 265 | 372 |
| 266 Bind(&switch_on_elements_kind); | 373 Bind(&switch_on_elements_kind); |
| 267 // Select by ElementsKind | 374 // Select by ElementsKind |
| 268 Node* o_map = LoadMap(o); | 375 Node* o_map = LoadMap(o); |
| 269 Node* bit_field2 = LoadMapBitField2(o_map); | 376 Node* bit_field2 = LoadMapBitField2(o_map); |
| 270 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 377 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| 271 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), | 378 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
| 272 &maybe_double_elements, &fast_elements); | 379 &maybe_double_elements, &fast_elements); |
| 273 | 380 |
| 274 ParameterMode mode = OptimalParameterMode(); | 381 ParameterMode mode = OptimalParameterMode(); |
| 275 Bind(&fast_elements); | 382 Bind(&fast_elements); |
| 276 { | 383 { |
| 277 Label array_changed(this, Label::kDeferred); | 384 Label array_changed(this, Label::kDeferred); |
| 278 Node* last_index = VisitAllFastElementsOneKind( | 385 Node* last_index = VisitAllFastElementsOneKind( |
| 279 context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a, | 386 context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a, |
| 280 &array_changed, mode); | 387 &array_changed, mode); |
| 281 | 388 |
| 389 action(this, context, a.value()); | |
| 390 | |
| 282 // No exception, return success | 391 // No exception, return success |
| 283 Return(a); | 392 Return(a.value()); |
| 284 | 393 |
| 285 Bind(&array_changed); | 394 Bind(&array_changed); |
| 286 k.Bind(ParameterToTagged(last_index, mode)); | 395 k.Bind(ParameterToTagged(last_index, mode)); |
| 287 Goto(slow); | 396 Goto(slow); |
| 288 } | 397 } |
| 289 | 398 |
| 290 Bind(&maybe_double_elements); | 399 Bind(&maybe_double_elements); |
| 291 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), | 400 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), |
| 292 slow, &fast_double_elements); | 401 slow, &fast_double_elements); |
| 293 | 402 |
| 294 Bind(&fast_double_elements); | 403 Bind(&fast_double_elements); |
| 295 { | 404 { |
| 296 Label array_changed(this, Label::kDeferred); | 405 Label array_changed(this, Label::kDeferred); |
| 297 Node* last_index = VisitAllFastElementsOneKind( | 406 Node* last_index = VisitAllFastElementsOneKind( |
| 298 context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn, | 407 context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn, |
| 299 processor, a, &array_changed, mode); | 408 processor, a, &array_changed, mode); |
| 300 | 409 |
| 410 action(this, context, a.value()); | |
| 411 | |
| 301 // No exception, return success | 412 // No exception, return success |
| 302 Return(a); | 413 Return(a.value()); |
| 303 | 414 |
| 304 Bind(&array_changed); | 415 Bind(&array_changed); |
| 305 k.Bind(ParameterToTagged(last_index, mode)); | 416 k.Bind(ParameterToTagged(last_index, mode)); |
| 306 Goto(slow); | 417 Goto(slow); |
| 307 } | 418 } |
| 308 } | 419 } |
| 309 }; | 420 }; |
| 310 | 421 |
| 311 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { | 422 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
| 312 Variable arg_index(this, MachineType::PointerRepresentation()); | 423 Variable arg_index(this, MachineType::PointerRepresentation()); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 { | 568 { |
| 458 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, | 569 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
| 459 MachineType::TaggedPointer()); | 570 MachineType::TaggedPointer()); |
| 460 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, | 571 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, |
| 461 argc); | 572 argc); |
| 462 } | 573 } |
| 463 } | 574 } |
| 464 | 575 |
| 465 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 576 TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 466 GenerateIteratingArrayBuiltinLoopContinuation( | 577 GenerateIteratingArrayBuiltinLoopContinuation( |
| 467 [this](Node* a, Node* p_k, Node* value) { | 578 &ArrayBuiltinCodeStubAssembler::ForEachProcessor, |
| 468 ForEachProcessor(a, p_k, value); | 579 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 469 }); | |
| 470 } | 580 } |
| 471 | 581 |
| 472 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { | 582 TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { |
| 473 GenerateIteratingArrayBuiltinBody( | 583 GenerateIteratingArrayBuiltinBody( |
| 474 "Array.prototype.forEach", | 584 "Array.prototype.forEach", |
| 475 [=](Node*, Node*) { return UndefinedConstant(); }, | 585 &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator, |
| 476 [this](Node* a, Node* p_k, Node* value) { | 586 &ArrayBuiltinCodeStubAssembler::ForEachProcessor, |
| 477 ForEachProcessor(a, p_k, value); | 587 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, |
| 478 }, | |
| 479 CodeFactory::ArrayForEachLoopContinuation(isolate())); | 588 CodeFactory::ArrayForEachLoopContinuation(isolate())); |
| 480 } | 589 } |
| 481 | 590 |
| 482 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 591 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 483 GenerateIteratingArrayBuiltinLoopContinuation( | 592 GenerateIteratingArrayBuiltinLoopContinuation( |
| 484 [this](Node* a, Node* p_k, Node* value) { | 593 &ArrayBuiltinCodeStubAssembler::SomeProcessor, |
| 485 SomeProcessor(a, p_k, value); | 594 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 486 }); | |
| 487 } | 595 } |
| 488 | 596 |
| 489 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { | 597 TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { |
| 490 GenerateIteratingArrayBuiltinBody( | 598 GenerateIteratingArrayBuiltinBody( |
| 491 "Array.prototype.some", [=](Node*, Node*) { return FalseConstant(); }, | 599 "Array.prototype.some", |
| 492 [this](Node* a, Node* p_k, Node* value) { SomeProcessor(a, p_k, value); }, | 600 &ArrayBuiltinCodeStubAssembler::SomeResultGenerator, |
| 601 &ArrayBuiltinCodeStubAssembler::SomeProcessor, | |
| 602 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, | |
| 493 CodeFactory::ArraySomeLoopContinuation(isolate())); | 603 CodeFactory::ArraySomeLoopContinuation(isolate())); |
| 494 } | 604 } |
| 495 | 605 |
| 496 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { | 606 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
| 497 GenerateIteratingArrayBuiltinLoopContinuation( | 607 GenerateIteratingArrayBuiltinLoopContinuation( |
| 498 [this](Node* a, Node* p_k, Node* value) { | 608 &ArrayBuiltinCodeStubAssembler::EveryProcessor, |
| 499 EveryProcessor(a, p_k, value); | 609 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
| 500 }); | |
| 501 } | 610 } |
| 502 | 611 |
| 503 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { | 612 TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { |
| 504 GenerateIteratingArrayBuiltinBody( | 613 GenerateIteratingArrayBuiltinBody( |
| 505 "Array.prototype.every", [=](Node*, Node*) { return TrueConstant(); }, | 614 "Array.prototype.every", |
| 506 [this](Node* a, Node* p_k, Node* value) { | 615 &ArrayBuiltinCodeStubAssembler::EveryResultGenerator, |
| 507 EveryProcessor(a, p_k, value); | 616 &ArrayBuiltinCodeStubAssembler::EveryProcessor, |
| 508 }, | 617 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, |
| 509 CodeFactory::ArrayEveryLoopContinuation(isolate())); | 618 CodeFactory::ArrayEveryLoopContinuation(isolate())); |
| 510 } | 619 } |
| 511 | 620 |
| 621 TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) { | |
| 622 GenerateIteratingArrayBuiltinLoopContinuation( | |
| 623 &ArrayBuiltinCodeStubAssembler::ReduceProcessor, | |
| 624 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction); | |
| 625 } | |
| 626 | |
| 627 TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) { | |
| 628 GenerateIteratingArrayBuiltinBody( | |
| 629 "Array.prototype.reduce", | |
| 630 &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator, | |
| 631 &ArrayBuiltinCodeStubAssembler::ReduceProcessor, | |
| 632 &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction, | |
| 633 CodeFactory::ArrayReduceLoopContinuation(isolate())); | |
| 634 } | |
| 635 | |
| 512 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { | 636 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
| 513 Node* object = Parameter(1); | 637 Node* object = Parameter(1); |
| 514 Node* context = Parameter(4); | 638 Node* context = Parameter(4); |
| 515 | 639 |
| 516 Label call_runtime(this), return_true(this), return_false(this); | 640 Label call_runtime(this), return_true(this), return_false(this); |
| 517 | 641 |
| 518 GotoIf(TaggedIsSmi(object), &return_false); | 642 GotoIf(TaggedIsSmi(object), &return_false); |
| 519 Node* instance_type = LoadInstanceType(object); | 643 Node* instance_type = LoadInstanceType(object); |
| 520 | 644 |
| 521 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), | 645 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), |
| (...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1556 { | 1680 { |
| 1557 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); | 1681 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); |
| 1558 CallRuntime(Runtime::kThrowTypeError, context, message, | 1682 CallRuntime(Runtime::kThrowTypeError, context, message, |
| 1559 HeapConstant(operation)); | 1683 HeapConstant(operation)); |
| 1560 Unreachable(); | 1684 Unreachable(); |
| 1561 } | 1685 } |
| 1562 } | 1686 } |
| 1563 | 1687 |
| 1564 } // namespace internal | 1688 } // namespace internal |
| 1565 } // namespace v8 | 1689 } // namespace v8 |
| OLD | NEW |