Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: src/builtins/builtins-conversion.cc

Issue 2734323004: [cleanup] Refactor remaining builtins-*.cc to use TF_BUILTIN macro (Closed)
Patch Set: drop unused variable Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/builtins/builtins-date.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "src/objects-inl.h" 9 #include "src/objects-inl.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 class ConversionBuiltinsAssembler : public CodeStubAssembler {
15 public:
16 explicit ConversionBuiltinsAssembler(compiler::CodeAssemblerState* state)
17 : CodeStubAssembler(state) {}
18
19 protected:
20 void Generate_NonPrimitiveToPrimitive(ToPrimitiveHint hint);
21
22 void Generate_OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint);
23 };
24
14 Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) { 25 Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
15 switch (hint) { 26 switch (hint) {
16 case ToPrimitiveHint::kDefault: 27 case ToPrimitiveHint::kDefault:
17 return NonPrimitiveToPrimitive_Default(); 28 return NonPrimitiveToPrimitive_Default();
18 case ToPrimitiveHint::kNumber: 29 case ToPrimitiveHint::kNumber:
19 return NonPrimitiveToPrimitive_Number(); 30 return NonPrimitiveToPrimitive_Number();
20 case ToPrimitiveHint::kString: 31 case ToPrimitiveHint::kString:
21 return NonPrimitiveToPrimitive_String(); 32 return NonPrimitiveToPrimitive_String();
22 } 33 }
23 UNREACHABLE(); 34 UNREACHABLE();
24 return Handle<Code>::null(); 35 return Handle<Code>::null();
25 } 36 }
26 37
27 namespace {
28
29 // ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] ) 38 // ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] )
30 void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler, 39 void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive(
31 ToPrimitiveHint hint) { 40 ToPrimitiveHint hint) {
32 typedef CodeStubAssembler::Label Label; 41 Node* input = Parameter(TypeConversionDescriptor::kArgument);
33 typedef compiler::Node Node; 42 Node* context = Parameter(TypeConversionDescriptor::kContext);
34 typedef TypeConversionDescriptor Descriptor;
35
36 Node* input = assembler->Parameter(Descriptor::kArgument);
37 Node* context = assembler->Parameter(Descriptor::kContext);
38 43
39 // Lookup the @@toPrimitive property on the {input}. 44 // Lookup the @@toPrimitive property on the {input}.
40 Callable callable = CodeFactory::GetProperty(assembler->isolate()); 45 Callable callable = CodeFactory::GetProperty(isolate());
41 Node* to_primitive_symbol = 46 Node* to_primitive_symbol = HeapConstant(factory()->to_primitive_symbol());
42 assembler->HeapConstant(assembler->factory()->to_primitive_symbol());
43 Node* exotic_to_prim = 47 Node* exotic_to_prim =
44 assembler->CallStub(callable, context, input, to_primitive_symbol); 48 CallStub(callable, context, input, to_primitive_symbol);
45 49
46 // Check if {exotic_to_prim} is neither null nor undefined. 50 // Check if {exotic_to_prim} is neither null nor undefined.
47 Label ordinary_to_primitive(assembler); 51 Label ordinary_to_primitive(this);
48 assembler->GotoIf( 52 GotoIf(WordEqual(exotic_to_prim, NullConstant()), &ordinary_to_primitive);
49 assembler->WordEqual(exotic_to_prim, assembler->NullConstant()), 53 GotoIf(WordEqual(exotic_to_prim, UndefinedConstant()),
50 &ordinary_to_primitive); 54 &ordinary_to_primitive);
51 assembler->GotoIf(
52 assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()),
53 &ordinary_to_primitive);
54 { 55 {
55 // Invoke the {exotic_to_prim} method on the {input} with a string 56 // Invoke the {exotic_to_prim} method on the {input} with a string
56 // representation of the {hint}. 57 // representation of the {hint}.
57 Callable callable = CodeFactory::Call( 58 Callable callable =
58 assembler->isolate(), ConvertReceiverMode::kNotNullOrUndefined); 59 CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined);
59 Node* hint_string = assembler->HeapConstant( 60 Node* hint_string = HeapConstant(factory()->ToPrimitiveHintString(hint));
60 assembler->factory()->ToPrimitiveHintString(hint)); 61 Node* result =
61 Node* result = assembler->CallJS(callable, context, exotic_to_prim, input, 62 CallJS(callable, context, exotic_to_prim, input, hint_string);
62 hint_string);
63 63
64 // Verify that the {result} is actually a primitive. 64 // Verify that the {result} is actually a primitive.
65 Label if_resultisprimitive(assembler), 65 Label if_resultisprimitive(this),
66 if_resultisnotprimitive(assembler, Label::kDeferred); 66 if_resultisnotprimitive(this, Label::kDeferred);
67 assembler->GotoIf(assembler->TaggedIsSmi(result), &if_resultisprimitive); 67 GotoIf(TaggedIsSmi(result), &if_resultisprimitive);
68 Node* result_instance_type = assembler->LoadInstanceType(result); 68 Node* result_instance_type = LoadInstanceType(result);
69 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 69 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
70 assembler->Branch(assembler->Int32LessThanOrEqual( 70 Branch(Int32LessThanOrEqual(result_instance_type,
71 result_instance_type, 71 Int32Constant(LAST_PRIMITIVE_TYPE)),
72 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), 72 &if_resultisprimitive, &if_resultisnotprimitive);
73 &if_resultisprimitive, &if_resultisnotprimitive);
74 73
75 assembler->Bind(&if_resultisprimitive); 74 Bind(&if_resultisprimitive);
76 { 75 {
77 // Just return the {result}. 76 // Just return the {result}.
78 assembler->Return(result); 77 Return(result);
79 } 78 }
80 79
81 assembler->Bind(&if_resultisnotprimitive); 80 Bind(&if_resultisnotprimitive);
82 { 81 {
83 // Somehow the @@toPrimitive method on {input} didn't yield a primitive. 82 // Somehow the @@toPrimitive method on {input} didn't yield a primitive.
84 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, 83 TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context);
85 context);
86 } 84 }
87 } 85 }
88 86
89 // Convert using the OrdinaryToPrimitive algorithm instead. 87 // Convert using the OrdinaryToPrimitive algorithm instead.
90 assembler->Bind(&ordinary_to_primitive); 88 Bind(&ordinary_to_primitive);
91 { 89 {
92 Callable callable = CodeFactory::OrdinaryToPrimitive( 90 Callable callable = CodeFactory::OrdinaryToPrimitive(
93 assembler->isolate(), (hint == ToPrimitiveHint::kString) 91 isolate(), (hint == ToPrimitiveHint::kString)
94 ? OrdinaryToPrimitiveHint::kString 92 ? OrdinaryToPrimitiveHint::kString
95 : OrdinaryToPrimitiveHint::kNumber); 93 : OrdinaryToPrimitiveHint::kNumber);
96 assembler->TailCallStub(callable, context, input); 94 TailCallStub(callable, context, input);
97 } 95 }
98 } 96 }
99 97
100 } // namespace 98 TF_BUILTIN(NonPrimitiveToPrimitive_Default, ConversionBuiltinsAssembler) {
101 99 Generate_NonPrimitiveToPrimitive(ToPrimitiveHint::kDefault);
102 void Builtins::Generate_NonPrimitiveToPrimitive_Default(
103 compiler::CodeAssemblerState* state) {
104 CodeStubAssembler assembler(state);
105 Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kDefault);
106 } 100 }
107 101
108 void Builtins::Generate_NonPrimitiveToPrimitive_Number( 102 TF_BUILTIN(NonPrimitiveToPrimitive_Number, ConversionBuiltinsAssembler) {
109 compiler::CodeAssemblerState* state) { 103 Generate_NonPrimitiveToPrimitive(ToPrimitiveHint::kNumber);
110 CodeStubAssembler assembler(state);
111 Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kNumber);
112 } 104 }
113 105
114 void Builtins::Generate_NonPrimitiveToPrimitive_String( 106 TF_BUILTIN(NonPrimitiveToPrimitive_String, ConversionBuiltinsAssembler) {
115 compiler::CodeAssemblerState* state) { 107 Generate_NonPrimitiveToPrimitive(ToPrimitiveHint::kString);
116 CodeStubAssembler assembler(state);
117 Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kString);
118 } 108 }
119 109
120 void Builtins::Generate_StringToNumber(compiler::CodeAssemblerState* state) { 110 TF_BUILTIN(StringToNumber, CodeStubAssembler) {
121 typedef compiler::Node Node; 111 Node* input = Parameter(TypeConversionDescriptor::kArgument);
122 typedef TypeConversionDescriptor Descriptor; 112 Node* context = Parameter(TypeConversionDescriptor::kContext);
123 CodeStubAssembler assembler(state);
124 113
125 Node* input = assembler.Parameter(Descriptor::kArgument); 114 Return(StringToNumber(context, input));
126 Node* context = assembler.Parameter(Descriptor::kContext);
127
128 assembler.Return(assembler.StringToNumber(context, input));
129 } 115 }
130 116
131 void Builtins::Generate_ToName(compiler::CodeAssemblerState* state) { 117 TF_BUILTIN(ToName, CodeStubAssembler) {
132 typedef compiler::Node Node; 118 Node* input = Parameter(TypeConversionDescriptor::kArgument);
133 typedef TypeConversionDescriptor Descriptor; 119 Node* context = Parameter(TypeConversionDescriptor::kContext);
134 CodeStubAssembler assembler(state);
135 120
136 Node* input = assembler.Parameter(Descriptor::kArgument); 121 Return(ToName(context, input));
137 Node* context = assembler.Parameter(Descriptor::kContext);
138
139 assembler.Return(assembler.ToName(context, input));
140 } 122 }
141 123
142 // static 124 TF_BUILTIN(NonNumberToNumber, CodeStubAssembler) {
143 void Builtins::Generate_NonNumberToNumber(compiler::CodeAssemblerState* state) { 125 Node* input = Parameter(TypeConversionDescriptor::kArgument);
144 typedef compiler::Node Node; 126 Node* context = Parameter(TypeConversionDescriptor::kContext);
145 typedef TypeConversionDescriptor Descriptor;
146 CodeStubAssembler assembler(state);
147 127
148 Node* input = assembler.Parameter(Descriptor::kArgument); 128 Return(NonNumberToNumber(context, input));
149 Node* context = assembler.Parameter(Descriptor::kContext);
150
151 assembler.Return(assembler.NonNumberToNumber(context, input));
152 } 129 }
153 130
154 // ES6 section 7.1.3 ToNumber ( argument ) 131 // ES6 section 7.1.3 ToNumber ( argument )
155 void Builtins::Generate_ToNumber(compiler::CodeAssemblerState* state) { 132 TF_BUILTIN(ToNumber, CodeStubAssembler) {
156 typedef compiler::Node Node; 133 Node* input = Parameter(TypeConversionDescriptor::kArgument);
157 typedef TypeConversionDescriptor Descriptor; 134 Node* context = Parameter(TypeConversionDescriptor::kContext);
158 CodeStubAssembler assembler(state);
159 135
160 Node* input = assembler.Parameter(Descriptor::kArgument); 136 Return(ToNumber(context, input));
161 Node* context = assembler.Parameter(Descriptor::kContext);
162
163 assembler.Return(assembler.ToNumber(context, input));
164 } 137 }
165 138
166 void Builtins::Generate_ToString(compiler::CodeAssemblerState* state) { 139 TF_BUILTIN(ToString, CodeStubAssembler) {
167 typedef CodeStubAssembler::Label Label; 140 Node* input = Parameter(TypeConversionDescriptor::kArgument);
168 typedef compiler::Node Node; 141 Node* context = Parameter(TypeConversionDescriptor::kContext);
169 typedef TypeConversionDescriptor Descriptor;
170 CodeStubAssembler assembler(state);
171 142
172 Node* input = assembler.Parameter(Descriptor::kArgument); 143 Label is_number(this);
173 Node* context = assembler.Parameter(Descriptor::kContext); 144 Label runtime(this);
174 145
175 Label is_number(&assembler); 146 GotoIf(TaggedIsSmi(input), &is_number);
176 Label runtime(&assembler);
177 147
178 assembler.GotoIf(assembler.TaggedIsSmi(input), &is_number); 148 Node* input_map = LoadMap(input);
149 Node* input_instance_type = LoadMapInstanceType(input_map);
179 150
180 Node* input_map = assembler.LoadMap(input); 151 Label not_string(this);
181 Node* input_instance_type = assembler.LoadMapInstanceType(input_map); 152 GotoIfNot(IsStringInstanceType(input_instance_type), &not_string);
153 Return(input);
182 154
183 Label not_string(&assembler); 155 Label not_heap_number(this);
184 assembler.GotoIfNot(assembler.IsStringInstanceType(input_instance_type),
185 &not_string);
186 assembler.Return(input);
187 156
188 Label not_heap_number(&assembler); 157 Bind(&not_string);
158 { Branch(IsHeapNumberMap(input_map), &is_number, &not_heap_number); }
189 159
190 assembler.Bind(&not_string); 160 Bind(&is_number);
161 { Return(NumberToString(context, input)); }
162
163 Bind(&not_heap_number);
191 { 164 {
192 assembler.GotoIfNot(assembler.IsHeapNumberMap(input_map), &not_heap_number); 165 GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)),
193 assembler.Goto(&is_number); 166 &runtime);
167 Return(LoadObjectField(input, Oddball::kToStringOffset));
194 } 168 }
195 169
196 assembler.Bind(&is_number); 170 Bind(&runtime);
197 { assembler.Return(assembler.NumberToString(context, input)); } 171 { Return(CallRuntime(Runtime::kToString, context, input)); }
198
199 assembler.Bind(&not_heap_number);
200 {
201 assembler.GotoIf(
202 assembler.Word32NotEqual(input_instance_type,
203 assembler.Int32Constant(ODDBALL_TYPE)),
204 &runtime);
205 assembler.Return(
206 assembler.LoadObjectField(input, Oddball::kToStringOffset));
207 }
208
209 assembler.Bind(&runtime);
210 {
211 assembler.Return(assembler.CallRuntime(Runtime::kToString, context, input));
212 }
213 } 172 }
214 173
215 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { 174 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {
216 switch (hint) { 175 switch (hint) {
217 case OrdinaryToPrimitiveHint::kNumber: 176 case OrdinaryToPrimitiveHint::kNumber:
218 return OrdinaryToPrimitive_Number(); 177 return OrdinaryToPrimitive_Number();
219 case OrdinaryToPrimitiveHint::kString: 178 case OrdinaryToPrimitiveHint::kString:
220 return OrdinaryToPrimitive_String(); 179 return OrdinaryToPrimitive_String();
221 } 180 }
222 UNREACHABLE(); 181 UNREACHABLE();
223 return Handle<Code>::null(); 182 return Handle<Code>::null();
224 } 183 }
225 184
226 namespace {
227
228 // 7.1.1.1 OrdinaryToPrimitive ( O, hint ) 185 // 7.1.1.1 OrdinaryToPrimitive ( O, hint )
229 void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler, 186 void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive(
230 OrdinaryToPrimitiveHint hint) { 187 OrdinaryToPrimitiveHint hint) {
231 typedef CodeStubAssembler::Label Label; 188 Node* input = Parameter(TypeConversionDescriptor::kArgument);
232 typedef compiler::Node Node; 189 Node* context = Parameter(TypeConversionDescriptor::kContext);
233 typedef CodeStubAssembler::Variable Variable; 190
234 typedef TypeConversionDescriptor Descriptor; 191 Variable var_result(this, MachineRepresentation::kTagged);
235 192 Label return_result(this, &var_result);
236 Node* input = assembler->Parameter(Descriptor::kArgument);
237 Node* context = assembler->Parameter(Descriptor::kContext);
238
239 Variable var_result(assembler, MachineRepresentation::kTagged);
240 Label return_result(assembler, &var_result);
241 193
242 Handle<String> method_names[2]; 194 Handle<String> method_names[2];
243 switch (hint) { 195 switch (hint) {
244 case OrdinaryToPrimitiveHint::kNumber: 196 case OrdinaryToPrimitiveHint::kNumber:
245 method_names[0] = assembler->factory()->valueOf_string(); 197 method_names[0] = factory()->valueOf_string();
246 method_names[1] = assembler->factory()->toString_string(); 198 method_names[1] = factory()->toString_string();
247 break; 199 break;
248 case OrdinaryToPrimitiveHint::kString: 200 case OrdinaryToPrimitiveHint::kString:
249 method_names[0] = assembler->factory()->toString_string(); 201 method_names[0] = factory()->toString_string();
250 method_names[1] = assembler->factory()->valueOf_string(); 202 method_names[1] = factory()->valueOf_string();
251 break; 203 break;
252 } 204 }
253 for (Handle<String> name : method_names) { 205 for (Handle<String> name : method_names) {
254 // Lookup the {name} on the {input}. 206 // Lookup the {name} on the {input}.
255 Callable callable = CodeFactory::GetProperty(assembler->isolate()); 207 Callable callable = CodeFactory::GetProperty(isolate());
256 Node* name_string = assembler->HeapConstant(name); 208 Node* name_string = HeapConstant(name);
257 Node* method = assembler->CallStub(callable, context, input, name_string); 209 Node* method = CallStub(callable, context, input, name_string);
258 210
259 // Check if the {method} is callable. 211 // Check if the {method} is callable.
260 Label if_methodiscallable(assembler), 212 Label if_methodiscallable(this),
261 if_methodisnotcallable(assembler, Label::kDeferred); 213 if_methodisnotcallable(this, Label::kDeferred);
262 assembler->GotoIf(assembler->TaggedIsSmi(method), &if_methodisnotcallable); 214 GotoIf(TaggedIsSmi(method), &if_methodisnotcallable);
263 Node* method_map = assembler->LoadMap(method); 215 Node* method_map = LoadMap(method);
264 assembler->Branch(assembler->IsCallableMap(method_map), 216 Branch(IsCallableMap(method_map), &if_methodiscallable,
265 &if_methodiscallable, &if_methodisnotcallable); 217 &if_methodisnotcallable);
266 218
267 assembler->Bind(&if_methodiscallable); 219 Bind(&if_methodiscallable);
268 { 220 {
269 // Call the {method} on the {input}. 221 // Call the {method} on the {input}.
270 Callable callable = CodeFactory::Call( 222 Callable callable = CodeFactory::Call(
271 assembler->isolate(), ConvertReceiverMode::kNotNullOrUndefined); 223 isolate(), ConvertReceiverMode::kNotNullOrUndefined);
272 Node* result = assembler->CallJS(callable, context, method, input); 224 Node* result = CallJS(callable, context, method, input);
273 var_result.Bind(result); 225 var_result.Bind(result);
274 226
275 // Return the {result} if it is a primitive. 227 // Return the {result} if it is a primitive.
276 assembler->GotoIf(assembler->TaggedIsSmi(result), &return_result); 228 GotoIf(TaggedIsSmi(result), &return_result);
277 Node* result_instance_type = assembler->LoadInstanceType(result); 229 Node* result_instance_type = LoadInstanceType(result);
278 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 230 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
279 assembler->GotoIf(assembler->Int32LessThanOrEqual( 231 GotoIf(Int32LessThanOrEqual(result_instance_type,
280 result_instance_type, 232 Int32Constant(LAST_PRIMITIVE_TYPE)),
281 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), 233 &return_result);
282 &return_result);
283 } 234 }
284 235
285 // Just continue with the next {name} if the {method} is not callable. 236 // Just continue with the next {name} if the {method} is not callable.
286 assembler->Goto(&if_methodisnotcallable); 237 Goto(&if_methodisnotcallable);
287 assembler->Bind(&if_methodisnotcallable); 238 Bind(&if_methodisnotcallable);
288 } 239 }
289 240
290 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context); 241 TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context);
291 242
292 assembler->Bind(&return_result); 243 Bind(&return_result);
293 assembler->Return(var_result.value()); 244 Return(var_result.value());
294 } 245 }
295 246
296 } // namespace 247 TF_BUILTIN(OrdinaryToPrimitive_Number, ConversionBuiltinsAssembler) {
297 248 Generate_OrdinaryToPrimitive(OrdinaryToPrimitiveHint::kNumber);
298 void Builtins::Generate_OrdinaryToPrimitive_Number( 249 }
299 compiler::CodeAssemblerState* state) { 250
300 CodeStubAssembler assembler(state); 251 TF_BUILTIN(OrdinaryToPrimitive_String, ConversionBuiltinsAssembler) {
301 Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kNumber); 252 Generate_OrdinaryToPrimitive(OrdinaryToPrimitiveHint::kString);
302 }
303
304 void Builtins::Generate_OrdinaryToPrimitive_String(
305 compiler::CodeAssemblerState* state) {
306 CodeStubAssembler assembler(state);
307 Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kString);
308 } 253 }
309 254
310 // ES6 section 7.1.2 ToBoolean ( argument ) 255 // ES6 section 7.1.2 ToBoolean ( argument )
311 void Builtins::Generate_ToBoolean(compiler::CodeAssemblerState* state) { 256 TF_BUILTIN(ToBoolean, CodeStubAssembler) {
312 typedef compiler::Node Node; 257 Node* value = Parameter(TypeConversionDescriptor::kArgument);
313 typedef CodeStubAssembler::Label Label; 258
314 typedef TypeConversionDescriptor Descriptor; 259 Label return_true(this), return_false(this);
315 CodeStubAssembler assembler(state); 260 BranchIfToBooleanIsTrue(value, &return_true, &return_false);
316 261
317 Node* value = assembler.Parameter(Descriptor::kArgument); 262 Bind(&return_true);
318 263 Return(BooleanConstant(true));
319 Label return_true(&assembler), return_false(&assembler); 264
320 assembler.BranchIfToBooleanIsTrue(value, &return_true, &return_false); 265 Bind(&return_false);
321 266 Return(BooleanConstant(false));
322 assembler.Bind(&return_true); 267 }
323 assembler.Return(assembler.BooleanConstant(true)); 268
324 269 TF_BUILTIN(ToLength, CodeStubAssembler) {
325 assembler.Bind(&return_false); 270 Node* context = Parameter(1);
326 assembler.Return(assembler.BooleanConstant(false));
327 }
328
329 void Builtins::Generate_ToLength(compiler::CodeAssemblerState* state) {
330 typedef CodeStubAssembler::Label Label;
331 typedef compiler::Node Node;
332 typedef CodeStubAssembler::Variable Variable;
333 CodeStubAssembler assembler(state);
334
335 Node* context = assembler.Parameter(1);
336 271
337 // We might need to loop once for ToNumber conversion. 272 // We might need to loop once for ToNumber conversion.
338 Variable var_len(&assembler, MachineRepresentation::kTagged); 273 Variable var_len(this, MachineRepresentation::kTagged, Parameter(0));
339 Label loop(&assembler, &var_len); 274 Label loop(this, &var_len);
340 var_len.Bind(assembler.Parameter(0)); 275 Goto(&loop);
341 assembler.Goto(&loop); 276 Bind(&loop);
342 assembler.Bind(&loop);
343 { 277 {
344 // Shared entry points. 278 // Shared entry points.
345 Label return_len(&assembler), 279 Label return_len(this), return_two53minus1(this, Label::kDeferred),
346 return_two53minus1(&assembler, Label::kDeferred), 280 return_zero(this, Label::kDeferred);
347 return_zero(&assembler, Label::kDeferred);
348 281
349 // Load the current {len} value. 282 // Load the current {len} value.
350 Node* len = var_len.value(); 283 Node* len = var_len.value();
351 284
352 // Check if {len} is a positive Smi. 285 // Check if {len} is a positive Smi.
353 assembler.GotoIf(assembler.TaggedIsPositiveSmi(len), &return_len); 286 GotoIf(TaggedIsPositiveSmi(len), &return_len);
354 287
355 // Check if {len} is a (negative) Smi. 288 // Check if {len} is a (negative) Smi.
356 assembler.GotoIf(assembler.TaggedIsSmi(len), &return_zero); 289 GotoIf(TaggedIsSmi(len), &return_zero);
357 290
358 // Check if {len} is a HeapNumber. 291 // Check if {len} is a HeapNumber.
359 Label if_lenisheapnumber(&assembler), 292 Label if_lenisheapnumber(this),
360 if_lenisnotheapnumber(&assembler, Label::kDeferred); 293 if_lenisnotheapnumber(this, Label::kDeferred);
361 assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(len)), 294 Branch(IsHeapNumberMap(LoadMap(len)), &if_lenisheapnumber,
362 &if_lenisheapnumber, &if_lenisnotheapnumber); 295 &if_lenisnotheapnumber);
363 296
364 assembler.Bind(&if_lenisheapnumber); 297 Bind(&if_lenisheapnumber);
365 { 298 {
366 // Load the floating-point value of {len}. 299 // Load the floating-point value of {len}.
367 Node* len_value = assembler.LoadHeapNumberValue(len); 300 Node* len_value = LoadHeapNumberValue(len);
368 301
369 // Check if {len} is not greater than zero. 302 // Check if {len} is not greater than zero.
370 assembler.GotoIfNot(assembler.Float64GreaterThan( 303 GotoIfNot(Float64GreaterThan(len_value, Float64Constant(0.0)),
371 len_value, assembler.Float64Constant(0.0)), 304 &return_zero);
372 &return_zero);
373 305
374 // Check if {len} is greater than or equal to 2^53-1. 306 // Check if {len} is greater than or equal to 2^53-1.
375 assembler.GotoIf( 307 GotoIf(Float64GreaterThanOrEqual(len_value,
376 assembler.Float64GreaterThanOrEqual( 308 Float64Constant(kMaxSafeInteger)),
377 len_value, assembler.Float64Constant(kMaxSafeInteger)), 309 &return_two53minus1);
378 &return_two53minus1);
379 310
380 // Round the {len} towards -Infinity. 311 // Round the {len} towards -Infinity.
381 Node* value = assembler.Float64Floor(len_value); 312 Node* value = Float64Floor(len_value);
382 Node* result = assembler.ChangeFloat64ToTagged(value); 313 Node* result = ChangeFloat64ToTagged(value);
383 assembler.Return(result); 314 Return(result);
384 } 315 }
385 316
386 assembler.Bind(&if_lenisnotheapnumber); 317 Bind(&if_lenisnotheapnumber);
387 { 318 {
388 // Need to convert {len} to a Number first. 319 // Need to convert {len} to a Number first.
389 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 320 Callable callable = CodeFactory::NonNumberToNumber(isolate());
390 var_len.Bind(assembler.CallStub(callable, context, len)); 321 var_len.Bind(CallStub(callable, context, len));
391 assembler.Goto(&loop); 322 Goto(&loop);
392 } 323 }
393 324
394 assembler.Bind(&return_len); 325 Bind(&return_len);
395 assembler.Return(var_len.value()); 326 Return(var_len.value());
396 327
397 assembler.Bind(&return_two53minus1); 328 Bind(&return_two53minus1);
398 assembler.Return(assembler.NumberConstant(kMaxSafeInteger)); 329 Return(NumberConstant(kMaxSafeInteger));
399 330
400 assembler.Bind(&return_zero); 331 Bind(&return_zero);
401 assembler.Return(assembler.SmiConstant(Smi::kZero)); 332 Return(SmiConstant(Smi::kZero));
402 } 333 }
403 } 334 }
404 335
405 void Builtins::Generate_ToInteger(compiler::CodeAssemblerState* state) { 336 TF_BUILTIN(ToInteger, CodeStubAssembler) {
406 typedef TypeConversionDescriptor Descriptor; 337 Node* input = Parameter(TypeConversionDescriptor::kArgument);
407 CodeStubAssembler assembler(state); 338 Node* context = Parameter(TypeConversionDescriptor::kContext);
408 339
409 compiler::Node* input = assembler.Parameter(Descriptor::kArgument); 340 Return(ToInteger(context, input));
410 compiler::Node* context = assembler.Parameter(Descriptor::kContext);
411
412 assembler.Return(assembler.ToInteger(context, input));
413 } 341 }
414 342
415 // ES6 section 7.1.13 ToObject (argument) 343 // ES6 section 7.1.13 ToObject (argument)
416 void Builtins::Generate_ToObject(compiler::CodeAssemblerState* state) { 344 TF_BUILTIN(ToObject, CodeStubAssembler) {
417 typedef compiler::Node Node; 345 Label if_number(this, Label::kDeferred), if_notsmi(this), if_jsreceiver(this),
418 typedef CodeStubAssembler::Label Label; 346 if_noconstructor(this, Label::kDeferred), if_wrapjsvalue(this);
419 typedef CodeStubAssembler::Variable Variable; 347
420 typedef TypeConversionDescriptor Descriptor; 348 Node* object = Parameter(TypeConversionDescriptor::kArgument);
421 CodeStubAssembler assembler(state); 349 Node* context = Parameter(TypeConversionDescriptor::kContext);
422 350
423 Label if_number(&assembler, Label::kDeferred), if_notsmi(&assembler), 351 Variable constructor_function_index_var(this,
424 if_jsreceiver(&assembler), if_noconstructor(&assembler, Label::kDeferred),
425 if_wrapjsvalue(&assembler);
426
427 Node* object = assembler.Parameter(Descriptor::kArgument);
428 Node* context = assembler.Parameter(Descriptor::kContext);
429
430 Variable constructor_function_index_var(&assembler,
431 MachineType::PointerRepresentation()); 352 MachineType::PointerRepresentation());
432 353
433 assembler.Branch(assembler.TaggedIsSmi(object), &if_number, &if_notsmi); 354 Branch(TaggedIsSmi(object), &if_number, &if_notsmi);
434 355
435 assembler.Bind(&if_notsmi); 356 Bind(&if_notsmi);
436 Node* map = assembler.LoadMap(object); 357 Node* map = LoadMap(object);
437 358
438 assembler.GotoIf(assembler.IsHeapNumberMap(map), &if_number); 359 GotoIf(IsHeapNumberMap(map), &if_number);
439 360
440 Node* instance_type = assembler.LoadMapInstanceType(map); 361 Node* instance_type = LoadMapInstanceType(map);
441 assembler.GotoIf(assembler.IsJSReceiverInstanceType(instance_type), 362 GotoIf(IsJSReceiverInstanceType(instance_type), &if_jsreceiver);
442 &if_jsreceiver); 363
443 364 Node* constructor_function_index = LoadMapConstructorFunctionIndex(map);
444 Node* constructor_function_index = 365 GotoIf(WordEqual(constructor_function_index,
445 assembler.LoadMapConstructorFunctionIndex(map); 366 IntPtrConstant(Map::kNoConstructorFunctionIndex)),
446 assembler.GotoIf(assembler.WordEqual(constructor_function_index, 367 &if_noconstructor);
447 assembler.IntPtrConstant(
448 Map::kNoConstructorFunctionIndex)),
449 &if_noconstructor);
450 constructor_function_index_var.Bind(constructor_function_index); 368 constructor_function_index_var.Bind(constructor_function_index);
451 assembler.Goto(&if_wrapjsvalue); 369 Goto(&if_wrapjsvalue);
452 370
453 assembler.Bind(&if_number); 371 Bind(&if_number);
454 constructor_function_index_var.Bind( 372 constructor_function_index_var.Bind(
455 assembler.IntPtrConstant(Context::NUMBER_FUNCTION_INDEX)); 373 IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
456 assembler.Goto(&if_wrapjsvalue); 374 Goto(&if_wrapjsvalue);
457 375
458 assembler.Bind(&if_wrapjsvalue); 376 Bind(&if_wrapjsvalue);
459 Node* native_context = assembler.LoadNativeContext(context); 377 Node* native_context = LoadNativeContext(context);
460 Node* constructor = assembler.LoadFixedArrayElement( 378 Node* constructor = LoadFixedArrayElement(
461 native_context, constructor_function_index_var.value()); 379 native_context, constructor_function_index_var.value());
462 Node* initial_map = assembler.LoadObjectField( 380 Node* initial_map =
463 constructor, JSFunction::kPrototypeOrInitialMapOffset); 381 LoadObjectField(constructor, JSFunction::kPrototypeOrInitialMapOffset);
464 Node* js_value = assembler.Allocate(JSValue::kSize); 382 Node* js_value = Allocate(JSValue::kSize);
465 assembler.StoreMapNoWriteBarrier(js_value, initial_map); 383 StoreMapNoWriteBarrier(js_value, initial_map);
466 assembler.StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset, 384 StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
467 Heap::kEmptyFixedArrayRootIndex); 385 Heap::kEmptyFixedArrayRootIndex);
468 assembler.StoreObjectFieldRoot(js_value, JSObject::kElementsOffset, 386 StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
469 Heap::kEmptyFixedArrayRootIndex); 387 Heap::kEmptyFixedArrayRootIndex);
470 assembler.StoreObjectField(js_value, JSValue::kValueOffset, object); 388 StoreObjectField(js_value, JSValue::kValueOffset, object);
471 assembler.Return(js_value); 389 Return(js_value);
472 390
473 assembler.Bind(&if_noconstructor); 391 Bind(&if_noconstructor);
474 assembler.TailCallRuntime( 392 TailCallRuntime(
475 Runtime::kThrowUndefinedOrNullToObject, context, 393 Runtime::kThrowUndefinedOrNullToObject, context,
476 assembler.HeapConstant( 394 HeapConstant(factory()->NewStringFromAsciiChecked("ToObject", TENURED)));
477 assembler.factory()->NewStringFromAsciiChecked("ToObject", TENURED))); 395
478 396 Bind(&if_jsreceiver);
479 assembler.Bind(&if_jsreceiver); 397 Return(object);
480 assembler.Return(object);
481 } 398 }
482 399
483 // Deprecated ES5 [[Class]] internal property (used to implement %_ClassOf). 400 // Deprecated ES5 [[Class]] internal property (used to implement %_ClassOf).
484 void Builtins::Generate_ClassOf(compiler::CodeAssemblerState* state) { 401 TF_BUILTIN(ClassOf, CodeStubAssembler) {
485 typedef compiler::Node Node; 402 Node* object = Parameter(TypeofDescriptor::kObject);
486 typedef TypeofDescriptor Descriptor; 403
487 CodeStubAssembler assembler(state); 404 Return(ClassOf(object));
488
489 Node* object = assembler.Parameter(Descriptor::kObject);
490
491 assembler.Return(assembler.ClassOf(object));
492 } 405 }
493 406
494 // ES6 section 12.5.5 typeof operator 407 // ES6 section 12.5.5 typeof operator
495 void Builtins::Generate_Typeof(compiler::CodeAssemblerState* state) { 408 TF_BUILTIN(Typeof, CodeStubAssembler) {
496 typedef compiler::Node Node; 409 Node* object = Parameter(TypeofDescriptor::kObject);
497 typedef TypeofDescriptor Descriptor; 410 Node* context = Parameter(TypeofDescriptor::kContext);
498 CodeStubAssembler assembler(state); 411
499 412 Return(Typeof(object, context));
500 Node* object = assembler.Parameter(Descriptor::kObject);
501 Node* context = assembler.Parameter(Descriptor::kContext);
502
503 assembler.Return(assembler.Typeof(object, context));
504 } 413 }
505 414
506 } // namespace internal 415 } // namespace internal
507 } // namespace v8 416 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/builtins/builtins-date.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698