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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 void Builtins::Generate_StringToNumber(CodeStubAssembler* assembler) { | 112 void Builtins::Generate_StringToNumber(CodeStubAssembler* assembler) { |
113 typedef compiler::Node Node; | 113 typedef compiler::Node Node; |
114 typedef TypeConversionDescriptor Descriptor; | 114 typedef TypeConversionDescriptor Descriptor; |
115 | 115 |
116 Node* input = assembler->Parameter(Descriptor::kArgument); | 116 Node* input = assembler->Parameter(Descriptor::kArgument); |
117 Node* context = assembler->Parameter(Descriptor::kContext); | 117 Node* context = assembler->Parameter(Descriptor::kContext); |
118 | 118 |
119 assembler->Return(assembler->StringToNumber(context, input)); | 119 assembler->Return(assembler->StringToNumber(context, input)); |
120 } | 120 } |
121 | 121 |
122 // ES6 section 7.1.3 ToNumber ( argument ) | 122 // ES6 section 7.1.3 ToNumber ( argument ) |
Igor Sheludko
2016/09/09 11:33:15
// static
or remove it.
| |
123 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { | 123 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { |
124 typedef CodeStubAssembler::Label Label; | |
125 typedef compiler::Node Node; | 124 typedef compiler::Node Node; |
126 typedef CodeStubAssembler::Variable Variable; | |
127 typedef TypeConversionDescriptor Descriptor; | 125 typedef TypeConversionDescriptor Descriptor; |
128 | 126 |
129 Node* input = assembler->Parameter(Descriptor::kArgument); | 127 Node* input = assembler->Parameter(Descriptor::kArgument); |
130 Node* context = assembler->Parameter(Descriptor::kContext); | 128 Node* context = assembler->Parameter(Descriptor::kContext); |
131 | 129 |
132 // We might need to loop once here due to ToPrimitive conversions. | 130 assembler->Return(assembler->NonNumberToNumber(context, input)); |
133 Variable var_input(assembler, MachineRepresentation::kTagged); | 131 } |
134 Label loop(assembler, &var_input); | |
135 var_input.Bind(input); | |
136 assembler->Goto(&loop); | |
137 assembler->Bind(&loop); | |
138 { | |
139 // Load the current {input} value (known to be a HeapObject). | |
140 Node* input = var_input.value(); | |
141 | 132 |
142 // Dispatch on the {input} instance type. | 133 // static |
Igor Sheludko
2016/09/09 11:33:15
// ES6 section 7.1.3 ToNumber ( argument )
| |
143 Node* input_instance_type = assembler->LoadInstanceType(input); | 134 void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) { |
144 Label if_inputisstring(assembler), if_inputisoddball(assembler), | 135 typedef compiler::Node Node; |
145 if_inputisreceiver(assembler, Label::kDeferred), | 136 typedef TypeConversionDescriptor Descriptor; |
146 if_inputisother(assembler, Label::kDeferred); | |
147 assembler->GotoIf(assembler->Int32LessThan( | |
148 input_instance_type, | |
149 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
150 &if_inputisstring); | |
151 assembler->GotoIf( | |
152 assembler->Word32Equal(input_instance_type, | |
153 assembler->Int32Constant(ODDBALL_TYPE)), | |
154 &if_inputisoddball); | |
155 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
156 assembler->Branch(assembler->Int32GreaterThanOrEqual( | |
157 input_instance_type, | |
158 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)), | |
159 &if_inputisreceiver, &if_inputisother); | |
160 | 137 |
161 assembler->Bind(&if_inputisstring); | 138 Node* input = assembler->Parameter(Descriptor::kArgument); |
162 { | 139 Node* context = assembler->Parameter(Descriptor::kContext); |
163 // The {input} is a String, use the fast stub to convert it to a Number. | |
164 assembler->Return(assembler->StringToNumber(context, input)); | |
165 } | |
166 | 140 |
167 assembler->Bind(&if_inputisoddball); | 141 assembler->Return(assembler->ToNumber(context, input)); |
168 { | |
169 // The {input} is an Oddball, we just need to the Number value of it. | |
170 Node* result = | |
171 assembler->LoadObjectField(input, Oddball::kToNumberOffset); | |
172 assembler->Return(result); | |
173 } | |
174 | |
175 assembler->Bind(&if_inputisreceiver); | |
176 { | |
177 // The {input} is a JSReceiver, we need to convert it to a Primitive first | |
178 // using the ToPrimitive type conversion, preferably yielding a Number. | |
179 Callable callable = CodeFactory::NonPrimitiveToPrimitive( | |
180 assembler->isolate(), ToPrimitiveHint::kNumber); | |
181 Node* result = assembler->CallStub(callable, context, input); | |
182 | |
183 // Check if the {result} is already a Number. | |
184 Label if_resultisnumber(assembler), if_resultisnotnumber(assembler); | |
185 assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber); | |
186 Node* result_map = assembler->LoadMap(result); | |
187 assembler->Branch( | |
188 assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()), | |
189 &if_resultisnumber, &if_resultisnotnumber); | |
190 | |
191 assembler->Bind(&if_resultisnumber); | |
192 { | |
193 // The ToPrimitive conversion already gave us a Number, so we're done. | |
194 assembler->Return(result); | |
195 } | |
196 | |
197 assembler->Bind(&if_resultisnotnumber); | |
198 { | |
199 // We now have a Primitive {result}, but it's not yet a Number. | |
200 var_input.Bind(result); | |
201 assembler->Goto(&loop); | |
202 } | |
203 } | |
204 | |
205 assembler->Bind(&if_inputisother); | |
206 { | |
207 // The {input} is something else (i.e. Symbol or Simd128Value), let the | |
208 // runtime figure out the correct exception. | |
209 // Note: We cannot tail call to the runtime here, as js-to-wasm | |
210 // trampolines also use this code currently, and they declare all | |
211 // outgoing parameters as untagged, while we would push a tagged | |
212 // object here. | |
213 Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input); | |
214 assembler->Return(result); | |
215 } | |
216 } | |
217 } | 142 } |
218 | 143 |
219 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { | 144 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { |
220 switch (hint) { | 145 switch (hint) { |
221 case OrdinaryToPrimitiveHint::kNumber: | 146 case OrdinaryToPrimitiveHint::kNumber: |
222 return OrdinaryToPrimitive_Number(); | 147 return OrdinaryToPrimitive_Number(); |
223 case OrdinaryToPrimitiveHint::kString: | 148 case OrdinaryToPrimitiveHint::kString: |
224 return OrdinaryToPrimitive_String(); | 149 return OrdinaryToPrimitive_String(); |
225 } | 150 } |
226 UNREACHABLE(); | 151 UNREACHABLE(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
324 | 249 |
325 assembler->Bind(&return_true); | 250 assembler->Bind(&return_true); |
326 assembler->Return(assembler->BooleanConstant(true)); | 251 assembler->Return(assembler->BooleanConstant(true)); |
327 | 252 |
328 assembler->Bind(&return_false); | 253 assembler->Bind(&return_false); |
329 assembler->Return(assembler->BooleanConstant(false)); | 254 assembler->Return(assembler->BooleanConstant(false)); |
330 } | 255 } |
331 | 256 |
332 } // namespace internal | 257 } // namespace internal |
333 } // namespace v8 | 258 } // namespace v8 |
OLD | NEW |