OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 VisitForAccumulatorValue(stmt->enumerable()); | 810 VisitForAccumulatorValue(stmt->enumerable()); |
811 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 811 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
812 __ cmp(r0, ip); | 812 __ cmp(r0, ip); |
813 __ b(eq, &exit); | 813 __ b(eq, &exit); |
814 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 814 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
815 __ cmp(r0, ip); | 815 __ cmp(r0, ip); |
816 __ b(eq, &exit); | 816 __ b(eq, &exit); |
817 | 817 |
818 // Convert the object to a JS object. | 818 // Convert the object to a JS object. |
819 Label convert, done_convert; | 819 Label convert, done_convert; |
820 __ BranchOnSmi(r0, &convert); | 820 __ JumpIfSmi(r0, &convert); |
821 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 821 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
822 __ b(hs, &done_convert); | 822 __ b(hs, &done_convert); |
823 __ bind(&convert); | 823 __ bind(&convert); |
824 __ push(r0); | 824 __ push(r0); |
825 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); | 825 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); |
826 __ bind(&done_convert); | 826 __ bind(&done_convert); |
827 __ push(r0); | 827 __ push(r0); |
828 | 828 |
829 // BUG(867): Check cache validity in generated code. This is a fast | 829 // BUG(867): Check cache validity in generated code. This is a fast |
830 // case for the JSObject::IsSimpleEnum cache validity checks. If we | 830 // case for the JSObject::IsSimpleEnum cache validity checks. If we |
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 | 2128 |
2129 VisitForAccumulatorValue(args->at(0)); | 2129 VisitForAccumulatorValue(args->at(0)); |
2130 | 2130 |
2131 Label materialize_true, materialize_false; | 2131 Label materialize_true, materialize_false; |
2132 Label* if_true = NULL; | 2132 Label* if_true = NULL; |
2133 Label* if_false = NULL; | 2133 Label* if_false = NULL; |
2134 Label* fall_through = NULL; | 2134 Label* fall_through = NULL; |
2135 context()->PrepareTest(&materialize_true, &materialize_false, | 2135 context()->PrepareTest(&materialize_true, &materialize_false, |
2136 &if_true, &if_false, &fall_through); | 2136 &if_true, &if_false, &fall_through); |
2137 | 2137 |
2138 __ BranchOnSmi(r0, if_false); | 2138 __ JumpIfSmi(r0, if_false); |
2139 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 2139 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
2140 __ cmp(r0, ip); | 2140 __ cmp(r0, ip); |
2141 __ b(eq, if_true); | 2141 __ b(eq, if_true); |
2142 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2142 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
2143 // Undetectable objects behave like undefined when tested with typeof. | 2143 // Undetectable objects behave like undefined when tested with typeof. |
2144 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); | 2144 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); |
2145 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 2145 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
2146 __ b(ne, if_false); | 2146 __ b(ne, if_false); |
2147 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 2147 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
2148 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 2148 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
(...skipping 11 matching lines...) Expand all Loading... |
2160 | 2160 |
2161 VisitForAccumulatorValue(args->at(0)); | 2161 VisitForAccumulatorValue(args->at(0)); |
2162 | 2162 |
2163 Label materialize_true, materialize_false; | 2163 Label materialize_true, materialize_false; |
2164 Label* if_true = NULL; | 2164 Label* if_true = NULL; |
2165 Label* if_false = NULL; | 2165 Label* if_false = NULL; |
2166 Label* fall_through = NULL; | 2166 Label* fall_through = NULL; |
2167 context()->PrepareTest(&materialize_true, &materialize_false, | 2167 context()->PrepareTest(&materialize_true, &materialize_false, |
2168 &if_true, &if_false, &fall_through); | 2168 &if_true, &if_false, &fall_through); |
2169 | 2169 |
2170 __ BranchOnSmi(r0, if_false); | 2170 __ JumpIfSmi(r0, if_false); |
2171 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 2171 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
2172 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2172 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2173 Split(ge, if_true, if_false, fall_through); | 2173 Split(ge, if_true, if_false, fall_through); |
2174 | 2174 |
2175 context()->Plug(if_true, if_false); | 2175 context()->Plug(if_true, if_false); |
2176 } | 2176 } |
2177 | 2177 |
2178 | 2178 |
2179 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 2179 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
2180 ASSERT(args->length() == 1); | 2180 ASSERT(args->length() == 1); |
2181 | 2181 |
2182 VisitForAccumulatorValue(args->at(0)); | 2182 VisitForAccumulatorValue(args->at(0)); |
2183 | 2183 |
2184 Label materialize_true, materialize_false; | 2184 Label materialize_true, materialize_false; |
2185 Label* if_true = NULL; | 2185 Label* if_true = NULL; |
2186 Label* if_false = NULL; | 2186 Label* if_false = NULL; |
2187 Label* fall_through = NULL; | 2187 Label* fall_through = NULL; |
2188 context()->PrepareTest(&materialize_true, &materialize_false, | 2188 context()->PrepareTest(&materialize_true, &materialize_false, |
2189 &if_true, &if_false, &fall_through); | 2189 &if_true, &if_false, &fall_through); |
2190 | 2190 |
2191 __ BranchOnSmi(r0, if_false); | 2191 __ JumpIfSmi(r0, if_false); |
2192 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2192 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
2193 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 2193 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
2194 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 2194 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
2195 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2195 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2196 Split(ne, if_true, if_false, fall_through); | 2196 Split(ne, if_true, if_false, fall_through); |
2197 | 2197 |
2198 context()->Plug(if_true, if_false); | 2198 context()->Plug(if_true, if_false); |
2199 } | 2199 } |
2200 | 2200 |
2201 | 2201 |
(...skipping 25 matching lines...) Expand all Loading... |
2227 | 2227 |
2228 VisitForAccumulatorValue(args->at(0)); | 2228 VisitForAccumulatorValue(args->at(0)); |
2229 | 2229 |
2230 Label materialize_true, materialize_false; | 2230 Label materialize_true, materialize_false; |
2231 Label* if_true = NULL; | 2231 Label* if_true = NULL; |
2232 Label* if_false = NULL; | 2232 Label* if_false = NULL; |
2233 Label* fall_through = NULL; | 2233 Label* fall_through = NULL; |
2234 context()->PrepareTest(&materialize_true, &materialize_false, | 2234 context()->PrepareTest(&materialize_true, &materialize_false, |
2235 &if_true, &if_false, &fall_through); | 2235 &if_true, &if_false, &fall_through); |
2236 | 2236 |
2237 __ BranchOnSmi(r0, if_false); | 2237 __ JumpIfSmi(r0, if_false); |
2238 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); | 2238 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); |
2239 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2239 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2240 Split(eq, if_true, if_false, fall_through); | 2240 Split(eq, if_true, if_false, fall_through); |
2241 | 2241 |
2242 context()->Plug(if_true, if_false); | 2242 context()->Plug(if_true, if_false); |
2243 } | 2243 } |
2244 | 2244 |
2245 | 2245 |
2246 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 2246 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
2247 ASSERT(args->length() == 1); | 2247 ASSERT(args->length() == 1); |
2248 | 2248 |
2249 VisitForAccumulatorValue(args->at(0)); | 2249 VisitForAccumulatorValue(args->at(0)); |
2250 | 2250 |
2251 Label materialize_true, materialize_false; | 2251 Label materialize_true, materialize_false; |
2252 Label* if_true = NULL; | 2252 Label* if_true = NULL; |
2253 Label* if_false = NULL; | 2253 Label* if_false = NULL; |
2254 Label* fall_through = NULL; | 2254 Label* fall_through = NULL; |
2255 context()->PrepareTest(&materialize_true, &materialize_false, | 2255 context()->PrepareTest(&materialize_true, &materialize_false, |
2256 &if_true, &if_false, &fall_through); | 2256 &if_true, &if_false, &fall_through); |
2257 | 2257 |
2258 __ BranchOnSmi(r0, if_false); | 2258 __ JumpIfSmi(r0, if_false); |
2259 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 2259 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
2260 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2260 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2261 Split(eq, if_true, if_false, fall_through); | 2261 Split(eq, if_true, if_false, fall_through); |
2262 | 2262 |
2263 context()->Plug(if_true, if_false); | 2263 context()->Plug(if_true, if_false); |
2264 } | 2264 } |
2265 | 2265 |
2266 | 2266 |
2267 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 2267 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
2268 ASSERT(args->length() == 1); | 2268 ASSERT(args->length() == 1); |
2269 | 2269 |
2270 VisitForAccumulatorValue(args->at(0)); | 2270 VisitForAccumulatorValue(args->at(0)); |
2271 | 2271 |
2272 Label materialize_true, materialize_false; | 2272 Label materialize_true, materialize_false; |
2273 Label* if_true = NULL; | 2273 Label* if_true = NULL; |
2274 Label* if_false = NULL; | 2274 Label* if_false = NULL; |
2275 Label* fall_through = NULL; | 2275 Label* fall_through = NULL; |
2276 context()->PrepareTest(&materialize_true, &materialize_false, | 2276 context()->PrepareTest(&materialize_true, &materialize_false, |
2277 &if_true, &if_false, &fall_through); | 2277 &if_true, &if_false, &fall_through); |
2278 | 2278 |
2279 __ BranchOnSmi(r0, if_false); | 2279 __ JumpIfSmi(r0, if_false); |
2280 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 2280 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
2281 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2281 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2282 Split(eq, if_true, if_false, fall_through); | 2282 Split(eq, if_true, if_false, fall_through); |
2283 | 2283 |
2284 context()->Plug(if_true, if_false); | 2284 context()->Plug(if_true, if_false); |
2285 } | 2285 } |
2286 | 2286 |
2287 | 2287 |
2288 | 2288 |
2289 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 2289 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2376 } | 2376 } |
2377 | 2377 |
2378 | 2378 |
2379 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { | 2379 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { |
2380 ASSERT(args->length() == 1); | 2380 ASSERT(args->length() == 1); |
2381 Label done, null, function, non_function_constructor; | 2381 Label done, null, function, non_function_constructor; |
2382 | 2382 |
2383 VisitForAccumulatorValue(args->at(0)); | 2383 VisitForAccumulatorValue(args->at(0)); |
2384 | 2384 |
2385 // If the object is a smi, we return null. | 2385 // If the object is a smi, we return null. |
2386 __ BranchOnSmi(r0, &null); | 2386 __ JumpIfSmi(r0, &null); |
2387 | 2387 |
2388 // Check that the object is a JS object but take special care of JS | 2388 // Check that the object is a JS object but take special care of JS |
2389 // functions to make sure they have 'Function' as their class. | 2389 // functions to make sure they have 'Function' as their class. |
2390 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. | 2390 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. |
2391 __ b(lt, &null); | 2391 __ b(lt, &null); |
2392 | 2392 |
2393 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 2393 // As long as JS_FUNCTION_TYPE is the last instance type and it is |
2394 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 2394 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for |
2395 // LAST_JS_OBJECT_TYPE. | 2395 // LAST_JS_OBJECT_TYPE. |
2396 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 2396 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2527 } | 2527 } |
2528 | 2528 |
2529 | 2529 |
2530 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2530 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
2531 ASSERT(args->length() == 1); | 2531 ASSERT(args->length() == 1); |
2532 | 2532 |
2533 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2533 VisitForAccumulatorValue(args->at(0)); // Load the object. |
2534 | 2534 |
2535 Label done; | 2535 Label done; |
2536 // If the object is a smi return the object. | 2536 // If the object is a smi return the object. |
2537 __ BranchOnSmi(r0, &done); | 2537 __ JumpIfSmi(r0, &done); |
2538 // If the object is not a value type, return the object. | 2538 // If the object is not a value type, return the object. |
2539 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); | 2539 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
2540 __ b(ne, &done); | 2540 __ b(ne, &done); |
2541 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); | 2541 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
2542 | 2542 |
2543 __ bind(&done); | 2543 __ bind(&done); |
2544 context()->Plug(r0); | 2544 context()->Plug(r0); |
2545 } | 2545 } |
2546 | 2546 |
2547 | 2547 |
2548 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { | 2548 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { |
2549 // Load the arguments on the stack and call the runtime function. | 2549 // Load the arguments on the stack and call the runtime function. |
2550 ASSERT(args->length() == 2); | 2550 ASSERT(args->length() == 2); |
2551 VisitForStackValue(args->at(0)); | 2551 VisitForStackValue(args->at(0)); |
2552 VisitForStackValue(args->at(1)); | 2552 VisitForStackValue(args->at(1)); |
2553 __ CallRuntime(Runtime::kMath_pow, 2); | 2553 __ CallRuntime(Runtime::kMath_pow, 2); |
2554 context()->Plug(r0); | 2554 context()->Plug(r0); |
2555 } | 2555 } |
2556 | 2556 |
2557 | 2557 |
2558 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2558 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
2559 ASSERT(args->length() == 2); | 2559 ASSERT(args->length() == 2); |
2560 | 2560 |
2561 VisitForStackValue(args->at(0)); // Load the object. | 2561 VisitForStackValue(args->at(0)); // Load the object. |
2562 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2562 VisitForAccumulatorValue(args->at(1)); // Load the value. |
2563 __ pop(r1); // r0 = value. r1 = object. | 2563 __ pop(r1); // r0 = value. r1 = object. |
2564 | 2564 |
2565 Label done; | 2565 Label done; |
2566 // If the object is a smi, return the value. | 2566 // If the object is a smi, return the value. |
2567 __ BranchOnSmi(r1, &done); | 2567 __ JumpIfSmi(r1, &done); |
2568 | 2568 |
2569 // If the object is not a value type, return the value. | 2569 // If the object is not a value type, return the value. |
2570 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 2570 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
2571 __ b(ne, &done); | 2571 __ b(ne, &done); |
2572 | 2572 |
2573 // Store the value. | 2573 // Store the value. |
2574 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 2574 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
2575 // Update the write barrier. Save the value as it will be | 2575 // Update the write barrier. Save the value as it will be |
2576 // overwritten by the write barrier code and is needed afterward. | 2576 // overwritten by the write barrier code and is needed afterward. |
2577 __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); | 2577 __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3080 | 3080 |
3081 case Token::BIT_NOT: { | 3081 case Token::BIT_NOT: { |
3082 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 3082 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
3083 // The generic unary operation stub expects the argument to be | 3083 // The generic unary operation stub expects the argument to be |
3084 // in the accumulator register r0. | 3084 // in the accumulator register r0. |
3085 VisitForAccumulatorValue(expr->expression()); | 3085 VisitForAccumulatorValue(expr->expression()); |
3086 Label done; | 3086 Label done; |
3087 bool inline_smi_code = ShouldInlineSmiCase(expr->op()); | 3087 bool inline_smi_code = ShouldInlineSmiCase(expr->op()); |
3088 if (inline_smi_code) { | 3088 if (inline_smi_code) { |
3089 Label call_stub; | 3089 Label call_stub; |
3090 __ BranchOnNotSmi(r0, &call_stub); | 3090 __ JumpIfNotSmi(r0, &call_stub); |
3091 __ mvn(r0, Operand(r0)); | 3091 __ mvn(r0, Operand(r0)); |
3092 // Bit-clear inverted smi-tag. | 3092 // Bit-clear inverted smi-tag. |
3093 __ bic(r0, r0, Operand(kSmiTagMask)); | 3093 __ bic(r0, r0, Operand(kSmiTagMask)); |
3094 __ b(&done); | 3094 __ b(&done); |
3095 __ bind(&call_stub); | 3095 __ bind(&call_stub); |
3096 } | 3096 } |
3097 bool overwrite = expr->expression()->ResultOverwriteAllowed(); | 3097 bool overwrite = expr->expression()->ResultOverwriteAllowed(); |
3098 UnaryOpFlags flags = inline_smi_code | 3098 UnaryOpFlags flags = inline_smi_code |
3099 ? NO_UNARY_SMI_CODE_IN_STUB | 3099 ? NO_UNARY_SMI_CODE_IN_STUB |
3100 : NO_UNARY_FLAGS; | 3100 : NO_UNARY_FLAGS; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3167 EmitKeyedPropertyLoad(prop); | 3167 EmitKeyedPropertyLoad(prop); |
3168 } | 3168 } |
3169 } | 3169 } |
3170 | 3170 |
3171 // We need a second deoptimization point after loading the value | 3171 // We need a second deoptimization point after loading the value |
3172 // in case evaluating the property load my have a side effect. | 3172 // in case evaluating the property load my have a side effect. |
3173 PrepareForBailout(expr->increment(), TOS_REG); | 3173 PrepareForBailout(expr->increment(), TOS_REG); |
3174 | 3174 |
3175 // Call ToNumber only if operand is not a smi. | 3175 // Call ToNumber only if operand is not a smi. |
3176 Label no_conversion; | 3176 Label no_conversion; |
3177 __ BranchOnSmi(r0, &no_conversion); | 3177 __ JumpIfSmi(r0, &no_conversion); |
3178 __ push(r0); | 3178 __ push(r0); |
3179 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 3179 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); |
3180 __ bind(&no_conversion); | 3180 __ bind(&no_conversion); |
3181 | 3181 |
3182 // Save result for postfix expressions. | 3182 // Save result for postfix expressions. |
3183 if (expr->is_postfix()) { | 3183 if (expr->is_postfix()) { |
3184 if (!context()->IsEffect()) { | 3184 if (!context()->IsEffect()) { |
3185 // Save the result on the stack. If we have a named or keyed property | 3185 // Save the result on the stack. If we have a named or keyed property |
3186 // we store the result under the receiver that is currently on top | 3186 // we store the result under the receiver that is currently on top |
3187 // of the stack. | 3187 // of the stack. |
(...skipping 13 matching lines...) Expand all Loading... |
3201 | 3201 |
3202 | 3202 |
3203 // Inline smi case if we are in a loop. | 3203 // Inline smi case if we are in a loop. |
3204 Label stub_call, done; | 3204 Label stub_call, done; |
3205 int count_value = expr->op() == Token::INC ? 1 : -1; | 3205 int count_value = expr->op() == Token::INC ? 1 : -1; |
3206 if (ShouldInlineSmiCase(expr->op())) { | 3206 if (ShouldInlineSmiCase(expr->op())) { |
3207 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); | 3207 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); |
3208 __ b(vs, &stub_call); | 3208 __ b(vs, &stub_call); |
3209 // We could eliminate this smi check if we split the code at | 3209 // We could eliminate this smi check if we split the code at |
3210 // the first smi check before calling ToNumber. | 3210 // the first smi check before calling ToNumber. |
3211 __ BranchOnSmi(r0, &done); | 3211 __ JumpIfSmi(r0, &done); |
3212 __ bind(&stub_call); | 3212 __ bind(&stub_call); |
3213 // Call stub. Undo operation first. | 3213 // Call stub. Undo operation first. |
3214 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 3214 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
3215 } | 3215 } |
3216 __ mov(r1, Operand(Smi::FromInt(count_value))); | 3216 __ mov(r1, Operand(Smi::FromInt(count_value))); |
3217 | 3217 |
3218 // Record position before stub call. | 3218 // Record position before stub call. |
3219 SetSourcePosition(expr->position()); | 3219 SetSourcePosition(expr->position()); |
3220 | 3220 |
3221 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); | 3221 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3494 case Token::IN: | 3494 case Token::IN: |
3495 case Token::INSTANCEOF: | 3495 case Token::INSTANCEOF: |
3496 default: | 3496 default: |
3497 UNREACHABLE(); | 3497 UNREACHABLE(); |
3498 } | 3498 } |
3499 | 3499 |
3500 bool inline_smi_code = ShouldInlineSmiCase(op); | 3500 bool inline_smi_code = ShouldInlineSmiCase(op); |
3501 if (inline_smi_code) { | 3501 if (inline_smi_code) { |
3502 Label slow_case; | 3502 Label slow_case; |
3503 __ orr(r2, r0, Operand(r1)); | 3503 __ orr(r2, r0, Operand(r1)); |
3504 __ BranchOnNotSmi(r2, &slow_case); | 3504 __ JumpIfNotSmi(r2, &slow_case); |
3505 __ cmp(r1, r0); | 3505 __ cmp(r1, r0); |
3506 Split(cc, if_true, if_false, NULL); | 3506 Split(cc, if_true, if_false, NULL); |
3507 __ bind(&slow_case); | 3507 __ bind(&slow_case); |
3508 } | 3508 } |
3509 CompareFlags flags = inline_smi_code | 3509 CompareFlags flags = inline_smi_code |
3510 ? NO_SMI_COMPARE_IN_STUB | 3510 ? NO_SMI_COMPARE_IN_STUB |
3511 : NO_COMPARE_FLAGS; | 3511 : NO_COMPARE_FLAGS; |
3512 CompareStub stub(cc, strict, flags, r1, r0); | 3512 CompareStub stub(cc, strict, flags, r1, r0); |
3513 __ CallStub(&stub); | 3513 __ CallStub(&stub); |
3514 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3514 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3616 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3616 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3617 __ add(pc, r1, Operand(masm_->CodeObject())); | 3617 __ add(pc, r1, Operand(masm_->CodeObject())); |
3618 } | 3618 } |
3619 | 3619 |
3620 | 3620 |
3621 #undef __ | 3621 #undef __ |
3622 | 3622 |
3623 } } // namespace v8::internal | 3623 } } // namespace v8::internal |
3624 | 3624 |
3625 #endif // V8_TARGET_ARCH_ARM | 3625 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |