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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 const $Array = global.Array; | 45 const $Array = global.Array; |
46 const $String = global.String; | 46 const $String = global.String; |
47 const $Number = global.Number; | 47 const $Number = global.Number; |
48 const $Function = global.Function; | 48 const $Function = global.Function; |
49 const $Boolean = global.Boolean; | 49 const $Boolean = global.Boolean; |
50 const $NaN = 0/0; | 50 const $NaN = 0/0; |
51 | 51 |
52 | 52 |
53 // ECMA-262, section 11.9.1, page 55. | 53 // ECMA-262, section 11.9.1, page 55. |
54 function EQUALS(y) { | 54 function EQUALS(y) { |
| 55 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y); |
55 var x = this; | 56 var x = this; |
56 | 57 |
57 // NOTE: We use iteration instead of recursion, because it is | 58 // NOTE: We use iteration instead of recursion, because it is |
58 // difficult to call EQUALS with the correct setting of 'this' in | 59 // difficult to call EQUALS with the correct setting of 'this' in |
59 // an efficient way. | 60 // an efficient way. |
60 | |
61 while (true) { | 61 while (true) { |
62 | |
63 if (IS_NUMBER(x)) { | 62 if (IS_NUMBER(x)) { |
64 if (y == null) return 1; // not equal | 63 if (y == null) return 1; // not equal |
65 return %NumberEquals(x, %ToNumber(y)); | 64 return %NumberEquals(x, %ToNumber(y)); |
66 | |
67 } else if (IS_STRING(x)) { | 65 } else if (IS_STRING(x)) { |
68 if (IS_STRING(y)) return %StringEquals(x, y); | 66 if (IS_STRING(y)) return %StringEquals(x, y); |
69 if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y); | 67 if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y); |
70 if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y)); | 68 if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y)); |
71 if (y == null) return 1; // not equal | 69 if (y == null) return 1; // not equal |
72 y = %ToPrimitive(y, NO_HINT); | 70 y = %ToPrimitive(y, NO_HINT); |
73 | |
74 } else if (IS_BOOLEAN(x)) { | 71 } else if (IS_BOOLEAN(x)) { |
75 if (IS_BOOLEAN(y)) { | 72 if (IS_BOOLEAN(y)) { |
76 return %_ObjectEquals(x, y) ? 0 : 1; | 73 return %_ObjectEquals(x, y) ? 0 : 1; |
77 } | 74 } |
78 if (y == null) return 1; // not equal | 75 if (y == null) return 1; // not equal |
79 return %NumberEquals(%ToNumber(x), %ToNumber(y)); | 76 return %NumberEquals(%ToNumber(x), %ToNumber(y)); |
80 | |
81 } else if (x == null) { | 77 } else if (x == null) { |
82 // NOTE: This checks for both null and undefined. | 78 // NOTE: This checks for both null and undefined. |
83 return (y == null) ? 0 : 1; | 79 return (y == null) ? 0 : 1; |
84 | |
85 } else { | 80 } else { |
86 if (IS_OBJECT(y)) { | 81 if (IS_OBJECT(y)) { |
87 return %_ObjectEquals(x, y) ? 0 : 1; | 82 return %_ObjectEquals(x, y) ? 0 : 1; |
88 } | 83 } |
89 if (IS_FUNCTION(y)) { | 84 if (IS_FUNCTION(y)) { |
90 return %_ObjectEquals(x, y) ? 0 : 1; | 85 return %_ObjectEquals(x, y) ? 0 : 1; |
91 } | 86 } |
92 x = %ToPrimitive(x, NO_HINT); | 87 x = %ToPrimitive(x, NO_HINT); |
93 | |
94 } | 88 } |
95 } | 89 } |
96 } | 90 } |
97 | 91 |
98 | |
99 // ECMA-262, section 11.9.4, page 56. | 92 // ECMA-262, section 11.9.4, page 56. |
100 function STRICT_EQUALS(x) { | 93 function STRICT_EQUALS(x) { |
101 if (IS_NUMBER(this)) { | 94 if (IS_NUMBER(this)) { |
102 if (!IS_NUMBER(x)) return 1; // not equal | 95 if (!IS_NUMBER(x)) return 1; // not equal |
103 return %NumberEquals(this, x); | 96 return %NumberEquals(this, x); |
104 } | 97 } |
105 | 98 |
106 if (IS_STRING(this)) { | 99 if (IS_STRING(this)) { |
107 if (!IS_STRING(x)) return 1; // not equal | 100 if (!IS_STRING(x)) return 1; // not equal |
108 return %StringEquals(this, x); | 101 return %StringEquals(this, x); |
109 } | 102 } |
110 | 103 |
111 if (IS_BOOLEAN(this)) { | 104 if (IS_BOOLEAN(this)) { |
112 if (!IS_BOOLEAN(x)) return 1; // not equal | 105 if (!IS_BOOLEAN(x)) return 1; // not equal |
113 if (this) return x ? 0 : 1; | 106 if (this) return x ? 0 : 1; |
114 else return x ? 1 : 0; | 107 else return x ? 1 : 0; |
115 } | 108 } |
116 | 109 |
117 if (IS_UNDEFINED(this)) { // both undefined and undetectable | 110 if (IS_UNDEFINED(this)) { // both undefined and undetectable |
118 return IS_UNDEFINED(x) ? 0 : 1; | 111 return IS_UNDEFINED(x) ? 0 : 1; |
119 } | 112 } |
120 | 113 |
121 return %_ObjectEquals(this, x) ? 0 : 1; | 114 return %_ObjectEquals(this, x) ? 0 : 1; |
122 } | 115 } |
123 | 116 |
124 | 117 |
125 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as | 118 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as |
126 // the result when either (or both) the operands are NaN. | 119 // the result when either (or both) the operands are NaN. |
127 function COMPARE(x, ncr) { | 120 function COMPARE(x, ncr) { |
128 // Improve performance for floating point compares | 121 // Fast case for numbers and strings. |
129 if (IS_NUMBER(this) && IS_NUMBER(x)) { | 122 if (IS_NUMBER(this) && IS_NUMBER(x)) { |
130 return %NumberCompare(this, x, ncr); | 123 return %NumberCompare(this, x, ncr); |
131 } | 124 } |
| 125 if (IS_STRING(this) && IS_STRING(x)) { |
| 126 return %StringCompare(this, x); |
| 127 } |
132 | 128 |
| 129 // Default implementation. |
133 var a = %ToPrimitive(this, NUMBER_HINT); | 130 var a = %ToPrimitive(this, NUMBER_HINT); |
134 var b = %ToPrimitive(x, NUMBER_HINT); | 131 var b = %ToPrimitive(x, NUMBER_HINT); |
135 if (IS_STRING(a) && IS_STRING(b)) { | 132 if (IS_STRING(a) && IS_STRING(b)) { |
136 return %StringCompare(a, b); | 133 return %StringCompare(a, b); |
137 } else { | 134 } else { |
138 return %NumberCompare(%ToNumber(a), %ToNumber(b), ncr); | 135 return %NumberCompare(%ToNumber(a), %ToNumber(b), ncr); |
139 } | 136 } |
140 } | 137 } |
141 | 138 |
142 | 139 |
143 | 140 |
144 /* ----------------------------------- | 141 /* ----------------------------------- |
145 - - - A r i t h m e t i c - - - | 142 - - - A r i t h m e t i c - - - |
146 ----------------------------------- | 143 ----------------------------------- |
147 */ | 144 */ |
148 | 145 |
149 // ECMA-262, section 11.6.1, page 50. | 146 // ECMA-262, section 11.6.1, page 50. |
150 function ADD(x) { | 147 function ADD(x) { |
151 // Fast case: Check for number operands and do the addition. | 148 // Fast case: Check for number operands and do the addition. |
152 if (IS_NUMBER(this) && IS_NUMBER(x)) { | 149 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
153 return %NumberAdd(this, x); | 150 if (IS_STRING(this) && IS_STRING(x)) return %StringAdd(this, x); |
154 } | |
155 | 151 |
| 152 // Default implementation. |
156 var a = %ToPrimitive(this, NO_HINT); | 153 var a = %ToPrimitive(this, NO_HINT); |
157 var b = %ToPrimitive(x, NO_HINT); | 154 var b = %ToPrimitive(x, NO_HINT); |
158 | 155 |
159 if (IS_STRING(a)) { | 156 if (IS_STRING(a)) { |
160 return %StringAdd(a, %ToString(b)); | 157 return %StringAdd(a, %ToString(b)); |
161 } else if (IS_STRING(b)) { | 158 } else if (IS_STRING(b)) { |
162 return %StringAdd(%ToString(a), b); | 159 return %StringAdd(%ToString(a), b); |
163 } else { | 160 } else { |
164 return %NumberAdd(%ToNumber(a), %ToNumber(b)); | 161 return %NumberAdd(%ToNumber(a), %ToNumber(b)); |
165 } | 162 } |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 | 387 |
391 | 388 |
392 /* ------------------------------------- | 389 /* ------------------------------------- |
393 - - - C o n v e r s i o n s - - - | 390 - - - C o n v e r s i o n s - - - |
394 ------------------------------------- | 391 ------------------------------------- |
395 */ | 392 */ |
396 | 393 |
397 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, | 394 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, |
398 // (1) for number hint, and (2) for string hint. | 395 // (1) for number hint, and (2) for string hint. |
399 function ToPrimitive(x, hint) { | 396 function ToPrimitive(x, hint) { |
| 397 // Fast case check. |
| 398 if (IS_STRING(x)) return x; |
| 399 if ((hint != NUMBER_HINT) && %IsStringClass(x)) return %_ValueOf(x); |
| 400 // Normal behaior. |
400 if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x; | 401 if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x; |
401 if (x == null) return x; // check for null, undefined | 402 if (x == null) return x; // check for null, undefined |
402 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; | 403 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; |
403 return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x); | 404 return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x); |
404 } | 405 } |
405 | 406 |
406 | 407 |
407 // ECMA-262, section 9.3, page 31. | 408 // ECMA-262, section 9.3, page 31. |
408 function ToNumber(x) { | 409 function ToNumber(x) { |
409 if (IS_NUMBER(x)) return x; | 410 if (IS_NUMBER(x)) return x; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 throw %MakeTypeError('cannot_convert_to_primitive', []); | 516 throw %MakeTypeError('cannot_convert_to_primitive', []); |
516 } | 517 } |
517 | 518 |
518 | 519 |
519 // NOTE: Setting the prototype for Array must take place as early as | 520 // NOTE: Setting the prototype for Array must take place as early as |
520 // possible due to code generation for array literals. When | 521 // possible due to code generation for array literals. When |
521 // generating code for a array literal a boilerplate array is created | 522 // generating code for a array literal a boilerplate array is created |
522 // that is cloned when running the code. It is essiential that the | 523 // that is cloned when running the code. It is essiential that the |
523 // boilerplate gets the right prototype. | 524 // boilerplate gets the right prototype. |
524 %FunctionSetPrototype($Array, new $Array(0)); | 525 %FunctionSetPrototype($Array, new $Array(0)); |
OLD | NEW |