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 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 158 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
159 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 159 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
160 | 160 |
161 // Default implementation. | 161 // Default implementation. |
162 var a = %ToPrimitive(this, NO_HINT); | 162 var a = %ToPrimitive(this, NO_HINT); |
163 var b = %ToPrimitive(x, NO_HINT); | 163 var b = %ToPrimitive(x, NO_HINT); |
164 | 164 |
165 if (IS_STRING(a)) { | 165 if (IS_STRING(a)) { |
166 return %_StringAdd(a, %ToString(b)); | 166 return %_StringAdd(a, %ToString(b)); |
167 } else if (IS_STRING(b)) { | 167 } else if (IS_STRING(b)) { |
168 return %_StringAdd(%ToString(a), b); | 168 return %_StringAdd(%NonStringToString(a), b); |
169 } else { | 169 } else { |
170 return %NumberAdd(%ToNumber(a), %ToNumber(b)); | 170 return %NumberAdd(%ToNumber(a), %ToNumber(b)); |
171 } | 171 } |
172 } | 172 } |
173 | 173 |
174 | 174 |
175 // Left operand (this) is already a string. | 175 // Left operand (this) is already a string. |
176 function STRING_ADD_LEFT(y) { | 176 function STRING_ADD_LEFT(y) { |
177 if (!IS_STRING(y)) { | 177 if (!IS_STRING(y)) { |
178 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 178 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
(...skipping 19 matching lines...) Expand all Loading... |
198 ? %_NumberToString(x) | 198 ? %_NumberToString(x) |
199 : %ToString(%ToPrimitive(x, NO_HINT)); | 199 : %ToString(%ToPrimitive(x, NO_HINT)); |
200 } | 200 } |
201 } | 201 } |
202 return %_StringAdd(x, y); | 202 return %_StringAdd(x, y); |
203 } | 203 } |
204 | 204 |
205 | 205 |
206 // ECMA-262, section 11.6.2, page 50. | 206 // ECMA-262, section 11.6.2, page 50. |
207 function SUB(y) { | 207 function SUB(y) { |
208 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 208 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
209 if (!IS_NUMBER(y)) y = %ToNumber(y); | 209 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
210 return %NumberSub(x, y); | 210 return %NumberSub(x, y); |
211 } | 211 } |
212 | 212 |
213 | 213 |
214 // ECMA-262, section 11.5.1, page 48. | 214 // ECMA-262, section 11.5.1, page 48. |
215 function MUL(y) { | 215 function MUL(y) { |
216 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 216 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
217 if (!IS_NUMBER(y)) y = %ToNumber(y); | 217 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
218 return %NumberMul(x, y); | 218 return %NumberMul(x, y); |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 // ECMA-262, section 11.5.2, page 49. | 222 // ECMA-262, section 11.5.2, page 49. |
223 function DIV(y) { | 223 function DIV(y) { |
224 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 224 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
225 if (!IS_NUMBER(y)) y = %ToNumber(y); | 225 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
226 return %NumberDiv(x, y); | 226 return %NumberDiv(x, y); |
227 } | 227 } |
228 | 228 |
229 | 229 |
230 // ECMA-262, section 11.5.3, page 49. | 230 // ECMA-262, section 11.5.3, page 49. |
231 function MOD(y) { | 231 function MOD(y) { |
232 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 232 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
233 if (!IS_NUMBER(y)) y = %ToNumber(y); | 233 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
234 return %NumberMod(x, y); | 234 return %NumberMod(x, y); |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 | 238 |
239 /* ------------------------------------------- | 239 /* ------------------------------------------- |
240 - - - B i t o p e r a t i o n s - - - | 240 - - - B i t o p e r a t i o n s - - - |
241 ------------------------------------------- | 241 ------------------------------------------- |
242 */ | 242 */ |
243 | 243 |
244 // ECMA-262, section 11.10, page 57. | 244 // ECMA-262, section 11.10, page 57. |
245 function BIT_OR(y) { | 245 function BIT_OR(y) { |
246 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 246 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
247 if (!IS_NUMBER(y)) y = %ToNumber(y); | 247 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
248 return %NumberOr(x, y); | 248 return %NumberOr(x, y); |
249 } | 249 } |
250 | 250 |
251 | 251 |
252 // ECMA-262, section 11.10, page 57. | 252 // ECMA-262, section 11.10, page 57. |
253 function BIT_AND(y) { | 253 function BIT_AND(y) { |
254 var x; | 254 var x; |
255 if (IS_NUMBER(this)) { | 255 if (IS_NUMBER(this)) { |
256 x = this; | 256 x = this; |
257 if (!IS_NUMBER(y)) y = %ToNumber(y); | 257 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
258 } else { | 258 } else { |
259 x = %ToNumber(this); | 259 x = %NonNumToNum(this); |
260 // Make sure to convert the right operand to a number before | 260 // Make sure to convert the right operand to a number before |
261 // bailing out in the fast case, but after converting the | 261 // bailing out in the fast case, but after converting the |
262 // left operand. This ensures that valueOf methods on the right | 262 // left operand. This ensures that valueOf methods on the right |
263 // operand are always executed. | 263 // operand are always executed. |
264 if (!IS_NUMBER(y)) y = %ToNumber(y); | 264 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
265 // Optimize for the case where we end up AND'ing a value | 265 // Optimize for the case where we end up AND'ing a value |
266 // that doesn't convert to a number. This is common in | 266 // that doesn't convert to a number. This is common in |
267 // certain benchmarks. | 267 // certain benchmarks. |
268 if (NUMBER_IS_NAN(x)) return 0; | 268 if (NUMBER_IS_NAN(x)) return 0; |
269 } | 269 } |
270 return %NumberAnd(x, y); | 270 return %NumberAnd(x, y); |
271 } | 271 } |
272 | 272 |
273 | 273 |
274 // ECMA-262, section 11.10, page 57. | 274 // ECMA-262, section 11.10, page 57. |
275 function BIT_XOR(y) { | 275 function BIT_XOR(y) { |
276 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 276 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
277 if (!IS_NUMBER(y)) y = %ToNumber(y); | 277 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
278 return %NumberXor(x, y); | 278 return %NumberXor(x, y); |
279 } | 279 } |
280 | 280 |
281 | 281 |
282 // ECMA-262, section 11.4.7, page 47. | 282 // ECMA-262, section 11.4.7, page 47. |
283 function UNARY_MINUS() { | 283 function UNARY_MINUS() { |
284 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 284 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
285 return %NumberUnaryMinus(x); | 285 return %NumberUnaryMinus(x); |
286 } | 286 } |
287 | 287 |
288 | 288 |
289 // ECMA-262, section 11.4.8, page 48. | 289 // ECMA-262, section 11.4.8, page 48. |
290 function BIT_NOT() { | 290 function BIT_NOT() { |
291 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 291 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
292 return %NumberNot(x); | 292 return %NumberNot(x); |
293 } | 293 } |
294 | 294 |
295 | 295 |
296 // ECMA-262, section 11.7.1, page 51. | 296 // ECMA-262, section 11.7.1, page 51. |
297 function SHL(y) { | 297 function SHL(y) { |
298 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 298 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
299 if (!IS_NUMBER(y)) y = %ToNumber(y); | 299 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
300 return %NumberShl(x, y); | 300 return %NumberShl(x, y); |
301 } | 301 } |
302 | 302 |
303 | 303 |
304 // ECMA-262, section 11.7.2, page 51. | 304 // ECMA-262, section 11.7.2, page 51. |
305 function SAR(y) { | 305 function SAR(y) { |
306 var x; | 306 var x; |
307 if (IS_NUMBER(this)) { | 307 if (IS_NUMBER(this)) { |
308 x = this; | 308 x = this; |
309 if (!IS_NUMBER(y)) y = %ToNumber(y); | 309 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
310 } else { | 310 } else { |
311 x = %ToNumber(this); | 311 x = %NonNumToNum(this); |
312 // Make sure to convert the right operand to a number before | 312 // Make sure to convert the right operand to a number before |
313 // bailing out in the fast case, but after converting the | 313 // bailing out in the fast case, but after converting the |
314 // left operand. This ensures that valueOf methods on the right | 314 // left operand. This ensures that valueOf methods on the right |
315 // operand are always executed. | 315 // operand are always executed. |
316 if (!IS_NUMBER(y)) y = %ToNumber(y); | 316 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
317 // Optimize for the case where we end up shifting a value | 317 // Optimize for the case where we end up shifting a value |
318 // that doesn't convert to a number. This is common in | 318 // that doesn't convert to a number. This is common in |
319 // certain benchmarks. | 319 // certain benchmarks. |
320 if (NUMBER_IS_NAN(x)) return 0; | 320 if (NUMBER_IS_NAN(x)) return 0; |
321 } | 321 } |
322 return %NumberSar(x, y); | 322 return %NumberSar(x, y); |
323 } | 323 } |
324 | 324 |
325 | 325 |
326 // ECMA-262, section 11.7.3, page 52. | 326 // ECMA-262, section 11.7.3, page 52. |
327 function SHR(y) { | 327 function SHR(y) { |
328 var x = IS_NUMBER(this) ? this : %ToNumber(this); | 328 var x = IS_NUMBER(this) ? this : %NonNumToNum(this); |
329 if (!IS_NUMBER(y)) y = %ToNumber(y); | 329 if (!IS_NUMBER(y)) y = %NonNumToNum(y); |
330 return %NumberShr(x, y); | 330 return %NumberShr(x, y); |
331 } | 331 } |
332 | 332 |
333 | 333 |
334 | 334 |
335 /* ----------------------------- | 335 /* ----------------------------- |
336 - - - H e l p e r s - - - | 336 - - - H e l p e r s - - - |
337 ----------------------------- | 337 ----------------------------- |
338 */ | 338 */ |
339 | 339 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 if (IS_NUMBER(x)) return x; | 504 if (IS_NUMBER(x)) return x; |
505 if (IS_STRING(x)) { | 505 if (IS_STRING(x)) { |
506 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x) | 506 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x) |
507 : %StringToNumber(x); | 507 : %StringToNumber(x); |
508 } | 508 } |
509 if (IS_BOOLEAN(x)) return x ? 1 : 0; | 509 if (IS_BOOLEAN(x)) return x ? 1 : 0; |
510 if (IS_UNDEFINED(x)) return $NaN; | 510 if (IS_UNDEFINED(x)) return $NaN; |
511 return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x)); | 511 return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x)); |
512 } | 512 } |
513 | 513 |
| 514 function NonNumToNum(x) { |
| 515 if (IS_STRING(x)) { |
| 516 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x) |
| 517 : %StringToNumber(x); |
| 518 } |
| 519 if (IS_BOOLEAN(x)) return x ? 1 : 0; |
| 520 if (IS_UNDEFINED(x)) return $NaN; |
| 521 return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x)); |
| 522 } |
| 523 |
514 | 524 |
515 // ECMA-262, section 9.8, page 35. | 525 // ECMA-262, section 9.8, page 35. |
516 function ToString(x) { | 526 function ToString(x) { |
517 if (IS_STRING(x)) return x; | 527 if (IS_STRING(x)) return x; |
518 if (IS_NUMBER(x)) return %_NumberToString(x); | 528 if (IS_NUMBER(x)) return %_NumberToString(x); |
519 if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; | 529 if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; |
520 if (IS_UNDEFINED(x)) return 'undefined'; | 530 if (IS_UNDEFINED(x)) return 'undefined'; |
521 return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x)); | 531 return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x)); |
522 } | 532 } |
523 | 533 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 return %NumberToJSInt32(ToNumber(x)); | 571 return %NumberToJSInt32(ToNumber(x)); |
562 } | 572 } |
563 | 573 |
564 | 574 |
565 // ES5, section 9.12 | 575 // ES5, section 9.12 |
566 function SameValue(x, y) { | 576 function SameValue(x, y) { |
567 if (typeof x != typeof y) return false; | 577 if (typeof x != typeof y) return false; |
568 if (IS_NUMBER(x)) { | 578 if (IS_NUMBER(x)) { |
569 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true; | 579 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true; |
570 // x is +0 and y is -0 or vice versa. | 580 // x is +0 and y is -0 or vice versa. |
571 if (x === 0 && y === 0 && (1 / x) != (1 / y)) { | 581 if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false; |
572 return false; | |
573 } | |
574 return x === y; | |
575 } | 582 } |
576 return x === y | 583 return x === y; |
577 } | 584 } |
578 | 585 |
579 | 586 |
580 /* --------------------------------- | 587 /* --------------------------------- |
581 - - - U t i l i t i e s - - - | 588 - - - U t i l i t i e s - - - |
582 --------------------------------- | 589 --------------------------------- |
583 */ | 590 */ |
584 | 591 |
585 // Returns if the given x is a primitive value - not an object or a | 592 // Returns if the given x is a primitive value - not an object or a |
586 // function. | 593 // function. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 throw %MakeTypeError('cannot_convert_to_primitive', []); | 634 throw %MakeTypeError('cannot_convert_to_primitive', []); |
628 } | 635 } |
629 | 636 |
630 | 637 |
631 // NOTE: Setting the prototype for Array must take place as early as | 638 // NOTE: Setting the prototype for Array must take place as early as |
632 // possible due to code generation for array literals. When | 639 // possible due to code generation for array literals. When |
633 // generating code for a array literal a boilerplate array is created | 640 // generating code for a array literal a boilerplate array is created |
634 // that is cloned when running the code. It is essiential that the | 641 // that is cloned when running the code. It is essiential that the |
635 // boilerplate gets the right prototype. | 642 // boilerplate gets the right prototype. |
636 %FunctionSetPrototype($Array, new $Array(0)); | 643 %FunctionSetPrototype($Array, new $Array(0)); |
OLD | NEW |