OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) { | 13 Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) { |
14 switch (hint) { | 14 switch (hint) { |
15 case ToPrimitiveHint::kDefault: | 15 case ToPrimitiveHint::kDefault: |
16 return NonPrimitiveToPrimitive_Default(); | 16 return NonPrimitiveToPrimitive_Default(); |
17 case ToPrimitiveHint::kNumber: | 17 case ToPrimitiveHint::kNumber: |
18 return NonPrimitiveToPrimitive_Number(); | 18 return NonPrimitiveToPrimitive_Number(); |
19 case ToPrimitiveHint::kString: | 19 case ToPrimitiveHint::kString: |
20 return NonPrimitiveToPrimitive_String(); | 20 return NonPrimitiveToPrimitive_String(); |
21 } | 21 } |
22 UNREACHABLE(); | 22 UNREACHABLE(); |
23 return Handle<Code>::null(); | 23 return Handle<Code>::null(); |
24 } | 24 } |
25 | 25 |
26 namespace { | 26 namespace { |
| 27 |
27 // ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] ) | 28 // ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] ) |
28 void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler, | 29 void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler, |
29 ToPrimitiveHint hint) { | 30 ToPrimitiveHint hint) { |
30 typedef CodeStubAssembler::Label Label; | 31 typedef CodeStubAssembler::Label Label; |
31 typedef compiler::Node Node; | 32 typedef compiler::Node Node; |
32 typedef TypeConversionDescriptor Descriptor; | 33 typedef TypeConversionDescriptor Descriptor; |
33 | 34 |
34 Node* input = assembler->Parameter(Descriptor::kArgument); | 35 Node* input = assembler->Parameter(Descriptor::kArgument); |
35 Node* context = assembler->Parameter(Descriptor::kContext); | 36 Node* context = assembler->Parameter(Descriptor::kContext); |
36 | 37 |
37 // Lookup the @@toPrimitive property on the {input}. | 38 // Lookup the @@toPrimitive property on the {input}. |
38 Callable callable = CodeFactory::GetProperty(assembler->isolate()); | 39 Callable callable = CodeFactory::GetProperty(assembler->isolate()); |
39 Node* to_primitive_symbol = | 40 Node* to_primitive_symbol = |
40 assembler->HeapConstant(assembler->factory()->to_primitive_symbol()); | 41 assembler->HeapConstant(assembler->factory()->to_primitive_symbol()); |
41 Node* exotic_to_prim = | 42 Node* exotic_to_prim = |
42 assembler->CallStub(callable, context, input, to_primitive_symbol); | 43 assembler->CallStub(callable, context, input, to_primitive_symbol); |
43 | 44 |
44 // Check if {exotic_to_prim} is neither null nor undefined. | 45 // Check if {exotic_to_prim} is neither null nor undefined. |
45 Label ordinary_to_primitive(assembler); | 46 Label ordinary_to_primitive(assembler); |
46 assembler->GotoIf( | 47 assembler->GotoIf( |
47 assembler->WordEqual(exotic_to_prim, assembler->NullConstant()), | 48 assembler->WordEqual(exotic_to_prim, assembler->NullConstant()), |
48 &ordinary_to_primitive); | 49 &ordinary_to_primitive); |
49 assembler->GotoIf( | 50 assembler->GotoIf( |
50 assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()), | 51 assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()), |
51 &ordinary_to_primitive); | 52 &ordinary_to_primitive); |
52 { | 53 { |
53 // Invoke the {exotic_to_prim} method on the {input} with a string | 54 // Invoke the {exotic_to_prim} method on the {input} with a string |
54 // representation of the {hint}. | 55 // representation of the {hint}. |
55 Callable callable = CodeFactory::Call(assembler->isolate()); | 56 Callable callable = CodeFactory::Call( |
| 57 assembler->isolate(), ConvertReceiverMode::kNotNullOrUndefined); |
56 Node* hint_string = assembler->HeapConstant( | 58 Node* hint_string = assembler->HeapConstant( |
57 assembler->factory()->ToPrimitiveHintString(hint)); | 59 assembler->factory()->ToPrimitiveHintString(hint)); |
58 Node* result = assembler->CallJS(callable, context, exotic_to_prim, input, | 60 Node* result = assembler->CallJS(callable, context, exotic_to_prim, input, |
59 hint_string); | 61 hint_string); |
60 | 62 |
61 // Verify that the {result} is actually a primitive. | 63 // Verify that the {result} is actually a primitive. |
62 Label if_resultisprimitive(assembler), | 64 Label if_resultisprimitive(assembler), |
63 if_resultisnotprimitive(assembler, Label::kDeferred); | 65 if_resultisnotprimitive(assembler, Label::kDeferred); |
64 assembler->GotoIf(assembler->TaggedIsSmi(result), &if_resultisprimitive); | 66 assembler->GotoIf(assembler->TaggedIsSmi(result), &if_resultisprimitive); |
65 Node* result_instance_type = assembler->LoadInstanceType(result); | 67 Node* result_instance_type = assembler->LoadInstanceType(result); |
(...skipping 20 matching lines...) Expand all Loading... |
86 // Convert using the OrdinaryToPrimitive algorithm instead. | 88 // Convert using the OrdinaryToPrimitive algorithm instead. |
87 assembler->Bind(&ordinary_to_primitive); | 89 assembler->Bind(&ordinary_to_primitive); |
88 { | 90 { |
89 Callable callable = CodeFactory::OrdinaryToPrimitive( | 91 Callable callable = CodeFactory::OrdinaryToPrimitive( |
90 assembler->isolate(), (hint == ToPrimitiveHint::kString) | 92 assembler->isolate(), (hint == ToPrimitiveHint::kString) |
91 ? OrdinaryToPrimitiveHint::kString | 93 ? OrdinaryToPrimitiveHint::kString |
92 : OrdinaryToPrimitiveHint::kNumber); | 94 : OrdinaryToPrimitiveHint::kNumber); |
93 assembler->TailCallStub(callable, context, input); | 95 assembler->TailCallStub(callable, context, input); |
94 } | 96 } |
95 } | 97 } |
96 } // anonymous namespace | 98 |
| 99 } // namespace |
97 | 100 |
98 void Builtins::Generate_NonPrimitiveToPrimitive_Default( | 101 void Builtins::Generate_NonPrimitiveToPrimitive_Default( |
99 compiler::CodeAssemblerState* state) { | 102 compiler::CodeAssemblerState* state) { |
100 CodeStubAssembler assembler(state); | 103 CodeStubAssembler assembler(state); |
101 Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kDefault); | 104 Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kDefault); |
102 } | 105 } |
103 | 106 |
104 void Builtins::Generate_NonPrimitiveToPrimitive_Number( | 107 void Builtins::Generate_NonPrimitiveToPrimitive_Number( |
105 compiler::CodeAssemblerState* state) { | 108 compiler::CodeAssemblerState* state) { |
106 CodeStubAssembler assembler(state); | 109 CodeStubAssembler assembler(state); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 case OrdinaryToPrimitiveHint::kNumber: | 217 case OrdinaryToPrimitiveHint::kNumber: |
215 return OrdinaryToPrimitive_Number(); | 218 return OrdinaryToPrimitive_Number(); |
216 case OrdinaryToPrimitiveHint::kString: | 219 case OrdinaryToPrimitiveHint::kString: |
217 return OrdinaryToPrimitive_String(); | 220 return OrdinaryToPrimitive_String(); |
218 } | 221 } |
219 UNREACHABLE(); | 222 UNREACHABLE(); |
220 return Handle<Code>::null(); | 223 return Handle<Code>::null(); |
221 } | 224 } |
222 | 225 |
223 namespace { | 226 namespace { |
| 227 |
224 // 7.1.1.1 OrdinaryToPrimitive ( O, hint ) | 228 // 7.1.1.1 OrdinaryToPrimitive ( O, hint ) |
225 void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler, | 229 void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler, |
226 OrdinaryToPrimitiveHint hint) { | 230 OrdinaryToPrimitiveHint hint) { |
227 typedef CodeStubAssembler::Label Label; | 231 typedef CodeStubAssembler::Label Label; |
228 typedef compiler::Node Node; | 232 typedef compiler::Node Node; |
229 typedef CodeStubAssembler::Variable Variable; | 233 typedef CodeStubAssembler::Variable Variable; |
230 typedef TypeConversionDescriptor Descriptor; | 234 typedef TypeConversionDescriptor Descriptor; |
231 | 235 |
232 Node* input = assembler->Parameter(Descriptor::kArgument); | 236 Node* input = assembler->Parameter(Descriptor::kArgument); |
233 Node* context = assembler->Parameter(Descriptor::kContext); | 237 Node* context = assembler->Parameter(Descriptor::kContext); |
(...skipping 22 matching lines...) Expand all Loading... |
256 Label if_methodiscallable(assembler), | 260 Label if_methodiscallable(assembler), |
257 if_methodisnotcallable(assembler, Label::kDeferred); | 261 if_methodisnotcallable(assembler, Label::kDeferred); |
258 assembler->GotoIf(assembler->TaggedIsSmi(method), &if_methodisnotcallable); | 262 assembler->GotoIf(assembler->TaggedIsSmi(method), &if_methodisnotcallable); |
259 Node* method_map = assembler->LoadMap(method); | 263 Node* method_map = assembler->LoadMap(method); |
260 assembler->Branch(assembler->IsCallableMap(method_map), | 264 assembler->Branch(assembler->IsCallableMap(method_map), |
261 &if_methodiscallable, &if_methodisnotcallable); | 265 &if_methodiscallable, &if_methodisnotcallable); |
262 | 266 |
263 assembler->Bind(&if_methodiscallable); | 267 assembler->Bind(&if_methodiscallable); |
264 { | 268 { |
265 // Call the {method} on the {input}. | 269 // Call the {method} on the {input}. |
266 Callable callable = CodeFactory::Call(assembler->isolate()); | 270 Callable callable = CodeFactory::Call( |
| 271 assembler->isolate(), ConvertReceiverMode::kNotNullOrUndefined); |
267 Node* result = assembler->CallJS(callable, context, method, input); | 272 Node* result = assembler->CallJS(callable, context, method, input); |
268 var_result.Bind(result); | 273 var_result.Bind(result); |
269 | 274 |
270 // Return the {result} if it is a primitive. | 275 // Return the {result} if it is a primitive. |
271 assembler->GotoIf(assembler->TaggedIsSmi(result), &return_result); | 276 assembler->GotoIf(assembler->TaggedIsSmi(result), &return_result); |
272 Node* result_instance_type = assembler->LoadInstanceType(result); | 277 Node* result_instance_type = assembler->LoadInstanceType(result); |
273 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); | 278 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); |
274 assembler->GotoIf(assembler->Int32LessThanOrEqual( | 279 assembler->GotoIf(assembler->Int32LessThanOrEqual( |
275 result_instance_type, | 280 result_instance_type, |
276 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), | 281 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), |
277 &return_result); | 282 &return_result); |
278 } | 283 } |
279 | 284 |
280 // Just continue with the next {name} if the {method} is not callable. | 285 // Just continue with the next {name} if the {method} is not callable. |
281 assembler->Goto(&if_methodisnotcallable); | 286 assembler->Goto(&if_methodisnotcallable); |
282 assembler->Bind(&if_methodisnotcallable); | 287 assembler->Bind(&if_methodisnotcallable); |
283 } | 288 } |
284 | 289 |
285 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context); | 290 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context); |
286 | 291 |
287 assembler->Bind(&return_result); | 292 assembler->Bind(&return_result); |
288 assembler->Return(var_result.value()); | 293 assembler->Return(var_result.value()); |
289 } | 294 } |
290 } // anonymous namespace | 295 |
| 296 } // namespace |
291 | 297 |
292 void Builtins::Generate_OrdinaryToPrimitive_Number( | 298 void Builtins::Generate_OrdinaryToPrimitive_Number( |
293 compiler::CodeAssemblerState* state) { | 299 compiler::CodeAssemblerState* state) { |
294 CodeStubAssembler assembler(state); | 300 CodeStubAssembler assembler(state); |
295 Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kNumber); | 301 Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kNumber); |
296 } | 302 } |
297 | 303 |
298 void Builtins::Generate_OrdinaryToPrimitive_String( | 304 void Builtins::Generate_OrdinaryToPrimitive_String( |
299 compiler::CodeAssemblerState* state) { | 305 compiler::CodeAssemblerState* state) { |
300 CodeStubAssembler assembler(state); | 306 CodeStubAssembler assembler(state); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 CodeStubAssembler assembler(state); | 498 CodeStubAssembler assembler(state); |
493 | 499 |
494 Node* object = assembler.Parameter(Descriptor::kObject); | 500 Node* object = assembler.Parameter(Descriptor::kObject); |
495 Node* context = assembler.Parameter(Descriptor::kContext); | 501 Node* context = assembler.Parameter(Descriptor::kContext); |
496 | 502 |
497 assembler.Return(assembler.Typeof(object, context)); | 503 assembler.Return(assembler.Typeof(object, context)); |
498 } | 504 } |
499 | 505 |
500 } // namespace internal | 506 } // namespace internal |
501 } // namespace v8 | 507 } // namespace v8 |
OLD | NEW |