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.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 void Builtins::Generate_ToName(CodeStubAssembler* assembler) { | 122 void Builtins::Generate_ToName(CodeStubAssembler* assembler) { |
123 typedef compiler::Node Node; | 123 typedef compiler::Node Node; |
124 typedef TypeConversionDescriptor Descriptor; | 124 typedef TypeConversionDescriptor Descriptor; |
125 | 125 |
126 Node* input = assembler->Parameter(Descriptor::kArgument); | 126 Node* input = assembler->Parameter(Descriptor::kArgument); |
127 Node* context = assembler->Parameter(Descriptor::kContext); | 127 Node* context = assembler->Parameter(Descriptor::kContext); |
128 | 128 |
129 assembler->Return(assembler->ToName(context, input)); | 129 assembler->Return(assembler->ToName(context, input)); |
130 } | 130 } |
131 | 131 |
132 // ES6 section 7.1.3 ToNumber ( argument ) | 132 // static |
133 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { | 133 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { |
134 typedef CodeStubAssembler::Label Label; | |
135 typedef compiler::Node Node; | 134 typedef compiler::Node Node; |
136 typedef CodeStubAssembler::Variable Variable; | |
137 typedef TypeConversionDescriptor Descriptor; | 135 typedef TypeConversionDescriptor Descriptor; |
138 | 136 |
139 Node* input = assembler->Parameter(Descriptor::kArgument); | 137 Node* input = assembler->Parameter(Descriptor::kArgument); |
140 Node* context = assembler->Parameter(Descriptor::kContext); | 138 Node* context = assembler->Parameter(Descriptor::kContext); |
141 | 139 |
142 // We might need to loop once here due to ToPrimitive conversions. | 140 assembler->Return(assembler->NonNumberToNumber(context, input)); |
143 Variable var_input(assembler, MachineRepresentation::kTagged); | 141 } |
144 Label loop(assembler, &var_input); | |
145 var_input.Bind(input); | |
146 assembler->Goto(&loop); | |
147 assembler->Bind(&loop); | |
148 { | |
149 // Load the current {input} value (known to be a HeapObject). | |
150 Node* input = var_input.value(); | |
151 | 142 |
152 // Dispatch on the {input} instance type. | 143 // ES6 section 7.1.3 ToNumber ( argument ) |
153 Node* input_instance_type = assembler->LoadInstanceType(input); | 144 void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) { |
154 Label if_inputisstring(assembler), if_inputisoddball(assembler), | 145 typedef compiler::Node Node; |
155 if_inputisreceiver(assembler, Label::kDeferred), | 146 typedef TypeConversionDescriptor Descriptor; |
156 if_inputisother(assembler, Label::kDeferred); | |
157 assembler->GotoIf(assembler->Int32LessThan( | |
158 input_instance_type, | |
159 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
160 &if_inputisstring); | |
161 assembler->GotoIf( | |
162 assembler->Word32Equal(input_instance_type, | |
163 assembler->Int32Constant(ODDBALL_TYPE)), | |
164 &if_inputisoddball); | |
165 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
166 assembler->Branch(assembler->Int32GreaterThanOrEqual( | |
167 input_instance_type, | |
168 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)), | |
169 &if_inputisreceiver, &if_inputisother); | |
170 | 147 |
171 assembler->Bind(&if_inputisstring); | 148 Node* input = assembler->Parameter(Descriptor::kArgument); |
172 { | 149 Node* context = assembler->Parameter(Descriptor::kContext); |
173 // The {input} is a String, use the fast stub to convert it to a Number. | |
174 assembler->Return(assembler->StringToNumber(context, input)); | |
175 } | |
176 | 150 |
177 assembler->Bind(&if_inputisoddball); | 151 assembler->Return(assembler->ToNumber(context, input)); |
178 { | |
179 // The {input} is an Oddball, we just need to the Number value of it. | |
180 Node* result = | |
181 assembler->LoadObjectField(input, Oddball::kToNumberOffset); | |
182 assembler->Return(result); | |
183 } | |
184 | |
185 assembler->Bind(&if_inputisreceiver); | |
186 { | |
187 // The {input} is a JSReceiver, we need to convert it to a Primitive first | |
188 // using the ToPrimitive type conversion, preferably yielding a Number. | |
189 Callable callable = CodeFactory::NonPrimitiveToPrimitive( | |
190 assembler->isolate(), ToPrimitiveHint::kNumber); | |
191 Node* result = assembler->CallStub(callable, context, input); | |
192 | |
193 // Check if the {result} is already a Number. | |
194 Label if_resultisnumber(assembler), if_resultisnotnumber(assembler); | |
195 assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber); | |
196 Node* result_map = assembler->LoadMap(result); | |
197 assembler->Branch( | |
198 assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()), | |
199 &if_resultisnumber, &if_resultisnotnumber); | |
200 | |
201 assembler->Bind(&if_resultisnumber); | |
202 { | |
203 // The ToPrimitive conversion already gave us a Number, so we're done. | |
204 assembler->Return(result); | |
205 } | |
206 | |
207 assembler->Bind(&if_resultisnotnumber); | |
208 { | |
209 // We now have a Primitive {result}, but it's not yet a Number. | |
210 var_input.Bind(result); | |
211 assembler->Goto(&loop); | |
212 } | |
213 } | |
214 | |
215 assembler->Bind(&if_inputisother); | |
216 { | |
217 // The {input} is something else (i.e. Symbol or Simd128Value), let the | |
218 // runtime figure out the correct exception. | |
219 // Note: We cannot tail call to the runtime here, as js-to-wasm | |
220 // trampolines also use this code currently, and they declare all | |
221 // outgoing parameters as untagged, while we would push a tagged | |
222 // object here. | |
223 Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input); | |
224 assembler->Return(result); | |
225 } | |
226 } | |
227 } | 152 } |
228 | 153 |
229 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { | 154 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { |
230 switch (hint) { | 155 switch (hint) { |
231 case OrdinaryToPrimitiveHint::kNumber: | 156 case OrdinaryToPrimitiveHint::kNumber: |
232 return OrdinaryToPrimitive_Number(); | 157 return OrdinaryToPrimitive_Number(); |
233 case OrdinaryToPrimitiveHint::kString: | 158 case OrdinaryToPrimitiveHint::kString: |
234 return OrdinaryToPrimitive_String(); | 159 return OrdinaryToPrimitive_String(); |
235 } | 160 } |
236 UNREACHABLE(); | 161 UNREACHABLE(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 | 259 |
335 assembler->Bind(&return_true); | 260 assembler->Bind(&return_true); |
336 assembler->Return(assembler->BooleanConstant(true)); | 261 assembler->Return(assembler->BooleanConstant(true)); |
337 | 262 |
338 assembler->Bind(&return_false); | 263 assembler->Bind(&return_false); |
339 assembler->Return(assembler->BooleanConstant(false)); | 264 assembler->Return(assembler->BooleanConstant(false)); |
340 } | 265 } |
341 | 266 |
342 } // namespace internal | 267 } // namespace internal |
343 } // namespace v8 | 268 } // namespace v8 |
OLD | NEW |