OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 // This files contains runtime support implemented in JavaScript. | 5 // This files contains runtime support implemented in JavaScript. |
6 | 6 |
7 // CAUTION: Some of the functions specified in this file are called | 7 // CAUTION: Some of the functions specified in this file are called |
8 // directly from compiled code. These are the functions with names in | 8 // directly from compiled code. These are the functions with names in |
9 // ALL CAPS. The compiled code passes the first argument in 'this'. | 9 // ALL CAPS. The compiled code passes the first argument in 'this'. |
10 | 10 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 throw %make_type_error(kStrongImplicitConversion); | 149 throw %make_type_error(kStrongImplicitConversion); |
150 } | 150 } |
151 | 151 |
152 | 152 |
153 | 153 |
154 /* ----------------------------------- | 154 /* ----------------------------------- |
155 - - - A r i t h m e t i c - - - | 155 - - - A r i t h m e t i c - - - |
156 ----------------------------------- | 156 ----------------------------------- |
157 */ | 157 */ |
158 | 158 |
159 // ECMA-262, section 11.6.1, page 50. | |
160 function ADD(x) { | |
161 // Fast case: Check for number operands and do the addition. | |
162 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | |
163 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | |
164 | |
165 // Default implementation. | |
166 var a = %to_primitive(this, NO_HINT); | |
167 var b = %to_primitive(x, NO_HINT); | |
168 | |
169 if (IS_STRING(a)) { | |
170 return %_StringAdd(a, %to_string_fun(b)); | |
171 } else if (IS_STRING(b)) { | |
172 return %_StringAdd(%non_string_to_string(a), b); | |
173 } else { | |
174 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); | |
175 } | |
176 } | |
177 | |
178 | |
179 // Strong mode ADD throws if an implicit conversion would be performed | |
180 function ADD_STRONG(x) { | |
181 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | |
182 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | |
183 | |
184 throw %make_type_error(kStrongImplicitConversion); | |
185 } | |
186 | |
187 | |
188 // Left operand (this) is already a string. | 159 // Left operand (this) is already a string. |
189 function STRING_ADD_LEFT(y) { | 160 function STRING_ADD_LEFT(y) { |
190 if (!IS_STRING(y)) { | 161 if (!IS_STRING(y)) { |
191 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 162 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
192 y = %_ValueOf(y); | 163 y = %_ValueOf(y); |
193 } else { | 164 } else { |
194 y = IS_NUMBER(y) | 165 y = IS_NUMBER(y) |
195 ? %_NumberToString(y) | 166 ? %_NumberToString(y) |
196 : %to_string_fun(%to_primitive(y, NO_HINT)); | 167 : %to_string_fun(%to_primitive(y, NO_HINT)); |
197 } | 168 } |
(...skipping 11 matching lines...) Expand all Loading... |
209 } else { | 180 } else { |
210 x = IS_NUMBER(x) | 181 x = IS_NUMBER(x) |
211 ? %_NumberToString(x) | 182 ? %_NumberToString(x) |
212 : %to_string_fun(%to_primitive(x, NO_HINT)); | 183 : %to_string_fun(%to_primitive(x, NO_HINT)); |
213 } | 184 } |
214 } | 185 } |
215 return %_StringAdd(x, y); | 186 return %_StringAdd(x, y); |
216 } | 187 } |
217 | 188 |
218 | 189 |
219 // ECMA-262, section 11.6.2, page 50. | |
220 function SUB(y) { | |
221 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
222 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
223 return %NumberSub(x, y); | |
224 } | |
225 | |
226 | |
227 // Strong mode SUB throws if an implicit conversion would be performed | |
228 function SUB_STRONG(y) { | |
229 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
230 return %NumberSub(this, y); | |
231 } | |
232 throw %make_type_error(kStrongImplicitConversion); | |
233 } | |
234 | |
235 | |
236 // ECMA-262, section 11.5.1, page 48. | |
237 function MUL(y) { | |
238 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
239 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
240 return %NumberMul(x, y); | |
241 } | |
242 | |
243 | |
244 // Strong mode MUL throws if an implicit conversion would be performed | |
245 function MUL_STRONG(y) { | |
246 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
247 return %NumberMul(this, y); | |
248 } | |
249 throw %make_type_error(kStrongImplicitConversion); | |
250 } | |
251 | |
252 | |
253 // ECMA-262, section 11.5.2, page 49. | |
254 function DIV(y) { | |
255 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
256 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
257 return %NumberDiv(x, y); | |
258 } | |
259 | |
260 | |
261 // Strong mode DIV throws if an implicit conversion would be performed | |
262 function DIV_STRONG(y) { | |
263 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
264 return %NumberDiv(this, y); | |
265 } | |
266 throw %make_type_error(kStrongImplicitConversion); | |
267 } | |
268 | |
269 | |
270 // ECMA-262, section 11.5.3, page 49. | |
271 function MOD(y) { | |
272 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
273 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
274 return %NumberMod(x, y); | |
275 } | |
276 | |
277 | |
278 // Strong mode MOD throws if an implicit conversion would be performed | |
279 function MOD_STRONG(y) { | |
280 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
281 return %NumberMod(this, y); | |
282 } | |
283 throw %make_type_error(kStrongImplicitConversion); | |
284 } | |
285 | |
286 | |
287 /* ------------------------------------------- | |
288 - - - B i t o p e r a t i o n s - - - | |
289 ------------------------------------------- | |
290 */ | |
291 | |
292 // ECMA-262, section 11.10, page 57. | |
293 function BIT_OR(y) { | |
294 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
295 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
296 return %NumberOr(x, y); | |
297 } | |
298 | |
299 | |
300 // Strong mode BIT_OR throws if an implicit conversion would be performed | |
301 function BIT_OR_STRONG(y) { | |
302 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
303 return %NumberOr(this, y); | |
304 } | |
305 throw %make_type_error(kStrongImplicitConversion); | |
306 } | |
307 | |
308 | |
309 // ECMA-262, section 11.10, page 57. | |
310 function BIT_AND(y) { | |
311 var x; | |
312 if (IS_NUMBER(this)) { | |
313 x = this; | |
314 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
315 } else { | |
316 x = %non_number_to_number(this); | |
317 // Make sure to convert the right operand to a number before | |
318 // bailing out in the fast case, but after converting the | |
319 // left operand. This ensures that valueOf methods on the right | |
320 // operand are always executed. | |
321 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
322 // Optimize for the case where we end up AND'ing a value | |
323 // that doesn't convert to a number. This is common in | |
324 // certain benchmarks. | |
325 if (NUMBER_IS_NAN(x)) return 0; | |
326 } | |
327 return %NumberAnd(x, y); | |
328 } | |
329 | |
330 | |
331 // Strong mode BIT_AND throws if an implicit conversion would be performed | |
332 function BIT_AND_STRONG(y) { | |
333 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
334 return %NumberAnd(this, y); | |
335 } | |
336 throw %make_type_error(kStrongImplicitConversion); | |
337 } | |
338 | |
339 | |
340 // ECMA-262, section 11.10, page 57. | |
341 function BIT_XOR(y) { | |
342 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
343 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
344 return %NumberXor(x, y); | |
345 } | |
346 | |
347 | |
348 // Strong mode BIT_XOR throws if an implicit conversion would be performed | |
349 function BIT_XOR_STRONG(y) { | |
350 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
351 return %NumberXor(this, y); | |
352 } | |
353 throw %make_type_error(kStrongImplicitConversion); | |
354 } | |
355 | |
356 | |
357 // ECMA-262, section 11.7.1, page 51. | |
358 function SHL(y) { | |
359 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
360 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
361 return %NumberShl(x, y); | |
362 } | |
363 | |
364 | |
365 // Strong mode SHL throws if an implicit conversion would be performed | |
366 function SHL_STRONG(y) { | |
367 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
368 return %NumberShl(this, y); | |
369 } | |
370 throw %make_type_error(kStrongImplicitConversion); | |
371 } | |
372 | |
373 | |
374 // ECMA-262, section 11.7.2, page 51. | |
375 function SAR(y) { | |
376 var x; | |
377 if (IS_NUMBER(this)) { | |
378 x = this; | |
379 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
380 } else { | |
381 x = %non_number_to_number(this); | |
382 // Make sure to convert the right operand to a number before | |
383 // bailing out in the fast case, but after converting the | |
384 // left operand. This ensures that valueOf methods on the right | |
385 // operand are always executed. | |
386 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
387 // Optimize for the case where we end up shifting a value | |
388 // that doesn't convert to a number. This is common in | |
389 // certain benchmarks. | |
390 if (NUMBER_IS_NAN(x)) return 0; | |
391 } | |
392 return %NumberSar(x, y); | |
393 } | |
394 | |
395 | |
396 // Strong mode SAR throws if an implicit conversion would be performed | |
397 function SAR_STRONG(y) { | |
398 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
399 return %NumberSar(this, y); | |
400 } | |
401 throw %make_type_error(kStrongImplicitConversion); | |
402 } | |
403 | |
404 | |
405 // ECMA-262, section 11.7.3, page 52. | |
406 function SHR(y) { | |
407 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
408 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
409 return %NumberShr(x, y); | |
410 } | |
411 | |
412 | |
413 // Strong mode SHR throws if an implicit conversion would be performed | |
414 function SHR_STRONG(y) { | |
415 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
416 return %NumberShr(this, y); | |
417 } | |
418 throw %make_type_error(kStrongImplicitConversion); | |
419 } | |
420 | |
421 | |
422 /* ----------------------------- | 190 /* ----------------------------- |
423 - - - H e l p e r s - - - | 191 - - - H e l p e r s - - - |
424 ----------------------------- | 192 ----------------------------- |
425 */ | 193 */ |
426 | 194 |
427 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { | 195 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { |
428 var delegate = %GetConstructorDelegate(this); | 196 var delegate = %GetConstructorDelegate(this); |
429 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); | 197 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); |
430 } | 198 } |
431 | 199 |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 $sameValue = SameValue; | 542 $sameValue = SameValue; |
775 $sameValueZero = SameValueZero; | 543 $sameValueZero = SameValueZero; |
776 $toInteger = ToInteger; | 544 $toInteger = ToInteger; |
777 $toLength = ToLength; | 545 $toLength = ToLength; |
778 $toNumber = ToNumber; | 546 $toNumber = ToNumber; |
779 $toPositiveInteger = ToPositiveInteger; | 547 $toPositiveInteger = ToPositiveInteger; |
780 $toPrimitive = ToPrimitive; | 548 $toPrimitive = ToPrimitive; |
781 $toString = ToString; | 549 $toString = ToString; |
782 | 550 |
783 %InstallToContext([ | 551 %InstallToContext([ |
784 "add_builtin", ADD, | |
785 "add_strong_builtin", ADD_STRONG, | |
786 "apply_prepare_builtin", APPLY_PREPARE, | 552 "apply_prepare_builtin", APPLY_PREPARE, |
787 "bit_and_builtin", BIT_AND, | |
788 "bit_and_strong_builtin", BIT_AND_STRONG, | |
789 "bit_or_builtin", BIT_OR, | |
790 "bit_or_strong_builtin", BIT_OR_STRONG, | |
791 "bit_xor_builtin", BIT_XOR, | |
792 "bit_xor_strong_builtin", BIT_XOR_STRONG, | |
793 "call_function_proxy_as_constructor_builtin", CALL_FUNCTION_PROXY_AS_CONSTRUCT
OR, | 553 "call_function_proxy_as_constructor_builtin", CALL_FUNCTION_PROXY_AS_CONSTRUCT
OR, |
794 "call_non_function_as_constructor_builtin", CALL_NON_FUNCTION_AS_CONSTRUCTOR, | 554 "call_non_function_as_constructor_builtin", CALL_NON_FUNCTION_AS_CONSTRUCTOR, |
795 "compare_builtin", COMPARE, | 555 "compare_builtin", COMPARE, |
796 "compare_strong_builtin", COMPARE_STRONG, | 556 "compare_strong_builtin", COMPARE_STRONG, |
797 "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY, | 557 "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY, |
798 "div_builtin", DIV, | |
799 "div_strong_builtin", DIV_STRONG, | |
800 "equals_builtin", EQUALS, | 558 "equals_builtin", EQUALS, |
801 "mod_builtin", MOD, | |
802 "mod_strong_builtin", MOD_STRONG, | |
803 "mul_builtin", MUL, | |
804 "mul_strong_builtin", MUL_STRONG, | |
805 "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE, | 559 "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE, |
806 "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE, | 560 "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE, |
807 "sar_builtin", SAR, | |
808 "sar_strong_builtin", SAR_STRONG, | |
809 "shl_builtin", SHL, | |
810 "shl_strong_builtin", SHL_STRONG, | |
811 "shr_builtin", SHR, | |
812 "shr_strong_builtin", SHR_STRONG, | |
813 "stack_overflow_builtin", STACK_OVERFLOW, | 561 "stack_overflow_builtin", STACK_OVERFLOW, |
814 "string_add_left_builtin", STRING_ADD_LEFT, | 562 "string_add_left_builtin", STRING_ADD_LEFT, |
815 "string_add_right_builtin", STRING_ADD_RIGHT, | 563 "string_add_right_builtin", STRING_ADD_RIGHT, |
816 "sub_builtin", SUB, | |
817 "sub_strong_builtin", SUB_STRONG, | |
818 ]); | 564 ]); |
819 | 565 |
820 %InstallToContext([ | 566 %InstallToContext([ |
821 "concat_iterable_to_array", ConcatIterableToArray, | 567 "concat_iterable_to_array", ConcatIterableToArray, |
822 "non_number_to_number", NonNumberToNumber, | 568 "non_number_to_number", NonNumberToNumber, |
823 "non_string_to_string", NonStringToString, | 569 "non_string_to_string", NonStringToString, |
824 "to_integer_fun", ToInteger, | 570 "to_integer_fun", ToInteger, |
825 "to_length_fun", ToLength, | 571 "to_length_fun", ToLength, |
826 "to_number_fun", ToNumber, | 572 "to_number_fun", ToNumber, |
827 "to_primitive", ToPrimitive, | 573 "to_primitive", ToPrimitive, |
828 "to_string_fun", ToString, | 574 "to_string_fun", ToString, |
829 ]); | 575 ]); |
830 | 576 |
831 utils.Export(function(to) { | 577 utils.Export(function(to) { |
832 to.ToBoolean = ToBoolean; | 578 to.ToBoolean = ToBoolean; |
833 to.ToLength = ToLength; | 579 to.ToLength = ToLength; |
834 to.ToNumber = ToNumber; | 580 to.ToNumber = ToNumber; |
835 to.ToPrimitive = ToPrimitive; | 581 to.ToPrimitive = ToPrimitive; |
836 to.ToString = ToString; | 582 to.ToString = ToString; |
837 }); | 583 }); |
838 | 584 |
839 }) | 585 }) |
OLD | NEW |