| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 if (false_label_ != fall_through_) __ b(false_label_); | 654 if (false_label_ != fall_through_) __ b(false_label_); |
| 655 } | 655 } |
| 656 } | 656 } |
| 657 | 657 |
| 658 | 658 |
| 659 void FullCodeGenerator::DoTest(Expression* condition, | 659 void FullCodeGenerator::DoTest(Expression* condition, |
| 660 Label* if_true, | 660 Label* if_true, |
| 661 Label* if_false, | 661 Label* if_false, |
| 662 Label* fall_through) { | 662 Label* fall_through) { |
| 663 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 663 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 664 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 664 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
| 665 __ tst(result_register(), result_register()); | 665 __ tst(result_register(), result_register()); |
| 666 Split(ne, if_true, if_false, fall_through); | 666 Split(ne, if_true, if_false, fall_through); |
| 667 } | 667 } |
| 668 | 668 |
| 669 | 669 |
| 670 void FullCodeGenerator::Split(Condition cond, | 670 void FullCodeGenerator::Split(Condition cond, |
| 671 Label* if_true, | 671 Label* if_true, |
| 672 Label* if_false, | 672 Label* if_false, |
| 673 Label* fall_through) { | 673 Label* fall_through) { |
| 674 if (if_false == fall_through) { | 674 if (if_false == fall_through) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 __ cmp(r1, r0); | 1015 __ cmp(r1, r0); |
| 1016 __ b(ne, &next_test); | 1016 __ b(ne, &next_test); |
| 1017 __ Drop(1); // Switch value is no longer needed. | 1017 __ Drop(1); // Switch value is no longer needed. |
| 1018 __ b(clause->body_target()); | 1018 __ b(clause->body_target()); |
| 1019 __ bind(&slow_case); | 1019 __ bind(&slow_case); |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 // Record position before stub call for type feedback. | 1022 // Record position before stub call for type feedback. |
| 1023 SetSourcePosition(clause->position()); | 1023 SetSourcePosition(clause->position()); |
| 1024 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1024 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1025 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 1025 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
| 1026 patch_site.EmitPatchInfo(); | 1026 patch_site.EmitPatchInfo(); |
| 1027 | 1027 |
| 1028 __ cmp(r0, Operand::Zero()); | 1028 __ cmp(r0, Operand::Zero()); |
| 1029 __ b(ne, &next_test); | 1029 __ b(ne, &next_test); |
| 1030 __ Drop(1); // Switch value is no longer needed. | 1030 __ Drop(1); // Switch value is no longer needed. |
| 1031 __ b(clause->body_target()); | 1031 __ b(clause->body_target()); |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 // Discard the test value and jump to the default if present, otherwise to | 1034 // Discard the test value and jump to the default if present, otherwise to |
| 1035 // the end of the statement. | 1035 // the end of the statement. |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 __ tst(temp, temp); | 1373 __ tst(temp, temp); |
| 1374 __ b(ne, slow); | 1374 __ b(ne, slow); |
| 1375 // Load next context in chain. | 1375 // Load next context in chain. |
| 1376 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); | 1376 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); |
| 1377 __ b(&loop); | 1377 __ b(&loop); |
| 1378 __ bind(&fast); | 1378 __ bind(&fast); |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 __ ldr(r0, GlobalObjectOperand()); | 1381 __ ldr(r0, GlobalObjectOperand()); |
| 1382 __ mov(r2, Operand(var->name())); | 1382 __ mov(r2, Operand(var->name())); |
| 1383 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1383 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
| 1384 ? RelocInfo::CODE_TARGET | 1384 ? NOT_CONTEXTUAL |
| 1385 : RelocInfo::CODE_TARGET_CONTEXT; | 1385 : CONTEXTUAL; |
| 1386 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1386 CallLoadIC(mode); |
| 1387 CallIC(ic, mode); | |
| 1388 } | 1387 } |
| 1389 | 1388 |
| 1390 | 1389 |
| 1391 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1390 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1392 Label* slow) { | 1391 Label* slow) { |
| 1393 ASSERT(var->IsContextSlot()); | 1392 ASSERT(var->IsContextSlot()); |
| 1394 Register context = cp; | 1393 Register context = cp; |
| 1395 Register next = r3; | 1394 Register next = r3; |
| 1396 Register temp = r4; | 1395 Register temp = r4; |
| 1397 | 1396 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 | 1459 |
| 1461 // Three cases: global variables, lookup variables, and all other types of | 1460 // Three cases: global variables, lookup variables, and all other types of |
| 1462 // variables. | 1461 // variables. |
| 1463 switch (var->location()) { | 1462 switch (var->location()) { |
| 1464 case Variable::UNALLOCATED: { | 1463 case Variable::UNALLOCATED: { |
| 1465 Comment cmnt(masm_, "Global variable"); | 1464 Comment cmnt(masm_, "Global variable"); |
| 1466 // Use inline caching. Variable name is passed in r2 and the global | 1465 // Use inline caching. Variable name is passed in r2 and the global |
| 1467 // object (receiver) in r0. | 1466 // object (receiver) in r0. |
| 1468 __ ldr(r0, GlobalObjectOperand()); | 1467 __ ldr(r0, GlobalObjectOperand()); |
| 1469 __ mov(r2, Operand(var->name())); | 1468 __ mov(r2, Operand(var->name())); |
| 1470 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1469 CallLoadIC(CONTEXTUAL); |
| 1471 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 1472 context()->Plug(r0); | 1470 context()->Plug(r0); |
| 1473 break; | 1471 break; |
| 1474 } | 1472 } |
| 1475 | 1473 |
| 1476 case Variable::PARAMETER: | 1474 case Variable::PARAMETER: |
| 1477 case Variable::LOCAL: | 1475 case Variable::LOCAL: |
| 1478 case Variable::CONTEXT: { | 1476 case Variable::CONTEXT: { |
| 1479 Comment cmnt(masm_, var->IsContextSlot() | 1477 Comment cmnt(masm_, var->IsContextSlot() |
| 1480 ? "Context variable" | 1478 ? "Context variable" |
| 1481 : "Stack variable"); | 1479 : "Stack variable"); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 UNREACHABLE(); | 1668 UNREACHABLE(); |
| 1671 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1669 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1672 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1670 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1673 // Fall through. | 1671 // Fall through. |
| 1674 case ObjectLiteral::Property::COMPUTED: | 1672 case ObjectLiteral::Property::COMPUTED: |
| 1675 if (key->value()->IsInternalizedString()) { | 1673 if (key->value()->IsInternalizedString()) { |
| 1676 if (property->emit_store()) { | 1674 if (property->emit_store()) { |
| 1677 VisitForAccumulatorValue(value); | 1675 VisitForAccumulatorValue(value); |
| 1678 __ mov(r2, Operand(key->value())); | 1676 __ mov(r2, Operand(key->value())); |
| 1679 __ ldr(r1, MemOperand(sp)); | 1677 __ ldr(r1, MemOperand(sp)); |
| 1680 Handle<Code> ic = is_classic_mode() | 1678 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
| 1681 ? isolate()->builtins()->StoreIC_Initialize() | |
| 1682 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 1683 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | |
| 1684 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1679 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1685 } else { | 1680 } else { |
| 1686 VisitForEffect(value); | 1681 VisitForEffect(value); |
| 1687 } | 1682 } |
| 1688 break; | 1683 break; |
| 1689 } | 1684 } |
| 1690 // Duplicate receiver on stack. | 1685 // Duplicate receiver on stack. |
| 1691 __ ldr(r0, MemOperand(sp)); | 1686 __ ldr(r0, MemOperand(sp)); |
| 1692 __ push(r0); | 1687 __ push(r0); |
| 1693 VisitForStackValue(key); | 1688 VisitForStackValue(key); |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 // result = receiver[f](arg); | 2076 // result = receiver[f](arg); |
| 2082 __ bind(&l_call); | 2077 __ bind(&l_call); |
| 2083 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2078 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2084 CallIC(ic); | 2079 CallIC(ic); |
| 2085 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2080 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2086 | 2081 |
| 2087 // if (!result.done) goto l_try; | 2082 // if (!result.done) goto l_try; |
| 2088 __ bind(&l_loop); | 2083 __ bind(&l_loop); |
| 2089 __ push(r0); // save result | 2084 __ push(r0); // save result |
| 2090 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" | 2085 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" |
| 2091 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 2086 CallLoadIC(NOT_CONTEXTUAL); // result.done in r0 |
| 2092 CallIC(done_ic); // result.done in r0 | |
| 2093 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2087 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2094 CallIC(bool_ic); | 2088 CallIC(bool_ic); |
| 2095 __ cmp(r0, Operand(0)); | 2089 __ cmp(r0, Operand(0)); |
| 2096 __ b(eq, &l_try); | 2090 __ b(eq, &l_try); |
| 2097 | 2091 |
| 2098 // result.value | 2092 // result.value |
| 2099 __ pop(r0); // result | 2093 __ pop(r0); // result |
| 2100 __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value" | 2094 __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value" |
| 2101 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | 2095 CallLoadIC(NOT_CONTEXTUAL); // result.value in r0 |
| 2102 CallIC(value_ic); // result.value in r0 | |
| 2103 context()->DropAndPlug(2, r0); // drop iter and g | 2096 context()->DropAndPlug(2, r0); // drop iter and g |
| 2104 break; | 2097 break; |
| 2105 } | 2098 } |
| 2106 } | 2099 } |
| 2107 } | 2100 } |
| 2108 | 2101 |
| 2109 | 2102 |
| 2110 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2103 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2111 Expression *value, | 2104 Expression *value, |
| 2112 JSGeneratorObject::ResumeMode resume_mode) { | 2105 JSGeneratorObject::ResumeMode resume_mode) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, | 2234 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, |
| 2242 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); | 2235 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
| 2243 } | 2236 } |
| 2244 | 2237 |
| 2245 | 2238 |
| 2246 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2239 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2247 SetSourcePosition(prop->position()); | 2240 SetSourcePosition(prop->position()); |
| 2248 Literal* key = prop->key()->AsLiteral(); | 2241 Literal* key = prop->key()->AsLiteral(); |
| 2249 __ mov(r2, Operand(key->value())); | 2242 __ mov(r2, Operand(key->value())); |
| 2250 // Call load IC. It has arguments receiver and property name r0 and r2. | 2243 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 2251 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2244 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2252 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | |
| 2253 } | 2245 } |
| 2254 | 2246 |
| 2255 | 2247 |
| 2256 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2248 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2257 SetSourcePosition(prop->position()); | 2249 SetSourcePosition(prop->position()); |
| 2258 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 2250 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 2259 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2251 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2260 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2252 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2261 } | 2253 } |
| 2262 | 2254 |
| 2263 | 2255 |
| 2264 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2256 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2265 Token::Value op, | 2257 Token::Value op, |
| 2266 OverwriteMode mode, | 2258 OverwriteMode mode, |
| 2267 Expression* left_expr, | 2259 Expression* left_expr, |
| 2268 Expression* right_expr) { | 2260 Expression* right_expr) { |
| 2269 Label done, smi_case, stub_call; | 2261 Label done, smi_case, stub_call; |
| 2270 | 2262 |
| 2271 Register scratch1 = r2; | 2263 Register scratch1 = r2; |
| 2272 Register scratch2 = r3; | 2264 Register scratch2 = r3; |
| 2273 | 2265 |
| 2274 // Get the arguments. | 2266 // Get the arguments. |
| 2275 Register left = r1; | 2267 Register left = r1; |
| 2276 Register right = r0; | 2268 Register right = r0; |
| 2277 __ pop(left); | 2269 __ pop(left); |
| 2278 | 2270 |
| 2279 // Perform combined smi check on both operands. | 2271 // Perform combined smi check on both operands. |
| 2280 __ orr(scratch1, left, Operand(right)); | 2272 __ orr(scratch1, left, Operand(right)); |
| 2281 STATIC_ASSERT(kSmiTag == 0); | 2273 STATIC_ASSERT(kSmiTag == 0); |
| 2282 JumpPatchSite patch_site(masm_); | 2274 JumpPatchSite patch_site(masm_); |
| 2283 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2275 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2284 | 2276 |
| 2285 __ bind(&stub_call); | 2277 __ bind(&stub_call); |
| 2286 BinaryOpICStub stub(op, mode); | 2278 BinaryOpICStub stub(op, mode); |
| 2287 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2279 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2288 expr->BinaryOperationFeedbackId()); | 2280 expr->BinaryOperationFeedbackId()); |
| 2289 patch_site.EmitPatchInfo(); | 2281 patch_site.EmitPatchInfo(); |
| 2290 __ jmp(&done); | 2282 __ jmp(&done); |
| 2291 | 2283 |
| 2292 __ bind(&smi_case); | 2284 __ bind(&smi_case); |
| 2293 // Smi case. This code works the same way as the smi-smi case in the type | 2285 // Smi case. This code works the same way as the smi-smi case in the type |
| 2294 // recording binary operation stub, see | 2286 // recording binary operation stub, see |
| 2295 switch (op) { | 2287 switch (op) { |
| 2296 case Token::SAR: | 2288 case Token::SAR: |
| 2297 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2289 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 context()->Plug(r0); | 2347 context()->Plug(r0); |
| 2356 } | 2348 } |
| 2357 | 2349 |
| 2358 | 2350 |
| 2359 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2351 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2360 Token::Value op, | 2352 Token::Value op, |
| 2361 OverwriteMode mode) { | 2353 OverwriteMode mode) { |
| 2362 __ pop(r1); | 2354 __ pop(r1); |
| 2363 BinaryOpICStub stub(op, mode); | 2355 BinaryOpICStub stub(op, mode); |
| 2364 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2356 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2365 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2357 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2366 expr->BinaryOperationFeedbackId()); | 2358 expr->BinaryOperationFeedbackId()); |
| 2367 patch_site.EmitPatchInfo(); | 2359 patch_site.EmitPatchInfo(); |
| 2368 context()->Plug(r0); | 2360 context()->Plug(r0); |
| 2369 } | 2361 } |
| 2370 | 2362 |
| 2371 | 2363 |
| 2372 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2364 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2373 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2365 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2374 // ReferenceError' on the left-hand side. | 2366 // ReferenceError' on the left-hand side. |
| 2375 if (!expr->IsValidLeftHandSide()) { | 2367 if (!expr->IsValidLeftHandSide()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2394 EffectContext context(this); | 2386 EffectContext context(this); |
| 2395 EmitVariableAssignment(var, Token::ASSIGN); | 2387 EmitVariableAssignment(var, Token::ASSIGN); |
| 2396 break; | 2388 break; |
| 2397 } | 2389 } |
| 2398 case NAMED_PROPERTY: { | 2390 case NAMED_PROPERTY: { |
| 2399 __ push(r0); // Preserve value. | 2391 __ push(r0); // Preserve value. |
| 2400 VisitForAccumulatorValue(prop->obj()); | 2392 VisitForAccumulatorValue(prop->obj()); |
| 2401 __ mov(r1, r0); | 2393 __ mov(r1, r0); |
| 2402 __ pop(r0); // Restore value. | 2394 __ pop(r0); // Restore value. |
| 2403 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2395 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2404 Handle<Code> ic = is_classic_mode() | 2396 CallStoreIC(NOT_CONTEXTUAL); |
| 2405 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2406 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2407 CallIC(ic); | |
| 2408 break; | 2397 break; |
| 2409 } | 2398 } |
| 2410 case KEYED_PROPERTY: { | 2399 case KEYED_PROPERTY: { |
| 2411 __ push(r0); // Preserve value. | 2400 __ push(r0); // Preserve value. |
| 2412 VisitForStackValue(prop->obj()); | 2401 VisitForStackValue(prop->obj()); |
| 2413 VisitForAccumulatorValue(prop->key()); | 2402 VisitForAccumulatorValue(prop->key()); |
| 2414 __ mov(r1, r0); | 2403 __ mov(r1, r0); |
| 2415 __ Pop(r0, r2); // r0 = restored value. | 2404 __ Pop(r0, r2); // r0 = restored value. |
| 2416 Handle<Code> ic = is_classic_mode() | 2405 Handle<Code> ic = is_classic_mode() |
| 2417 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2406 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2418 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2407 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2419 CallIC(ic); | 2408 CallIC(ic); |
| 2420 break; | 2409 break; |
| 2421 } | 2410 } |
| 2422 } | 2411 } |
| 2423 context()->Plug(r0); | 2412 context()->Plug(r0); |
| 2424 } | 2413 } |
| 2425 | 2414 |
| 2426 | 2415 |
| 2427 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2416 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2428 Token::Value op) { | 2417 Token::Value op) { |
| 2429 if (var->IsUnallocated()) { | 2418 if (var->IsUnallocated()) { |
| 2430 // Global var, const, or let. | 2419 // Global var, const, or let. |
| 2431 __ mov(r2, Operand(var->name())); | 2420 __ mov(r2, Operand(var->name())); |
| 2432 __ ldr(r1, GlobalObjectOperand()); | 2421 __ ldr(r1, GlobalObjectOperand()); |
| 2433 Handle<Code> ic = is_classic_mode() | 2422 CallStoreIC(CONTEXTUAL); |
| 2434 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2435 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2436 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 2437 | |
| 2438 } else if (op == Token::INIT_CONST) { | 2423 } else if (op == Token::INIT_CONST) { |
| 2439 // Const initializers need a write barrier. | 2424 // Const initializers need a write barrier. |
| 2440 ASSERT(!var->IsParameter()); // No const parameters. | 2425 ASSERT(!var->IsParameter()); // No const parameters. |
| 2441 if (var->IsStackLocal()) { | 2426 if (var->IsStackLocal()) { |
| 2442 Label skip; | 2427 Label skip; |
| 2443 __ ldr(r1, StackOperand(var)); | 2428 __ ldr(r1, StackOperand(var)); |
| 2444 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 2429 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
| 2445 __ b(ne, &skip); | 2430 __ b(ne, &skip); |
| 2446 __ str(result_register(), StackOperand(var)); | 2431 __ str(result_register(), StackOperand(var)); |
| 2447 __ bind(&skip); | 2432 __ bind(&skip); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2524 // Assignment to a property, using a named store IC. | 2509 // Assignment to a property, using a named store IC. |
| 2525 Property* prop = expr->target()->AsProperty(); | 2510 Property* prop = expr->target()->AsProperty(); |
| 2526 ASSERT(prop != NULL); | 2511 ASSERT(prop != NULL); |
| 2527 ASSERT(prop->key()->AsLiteral() != NULL); | 2512 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2528 | 2513 |
| 2529 // Record source code position before IC call. | 2514 // Record source code position before IC call. |
| 2530 SetSourcePosition(expr->position()); | 2515 SetSourcePosition(expr->position()); |
| 2531 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2516 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2532 __ pop(r1); | 2517 __ pop(r1); |
| 2533 | 2518 |
| 2534 Handle<Code> ic = is_classic_mode() | 2519 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2535 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2536 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2537 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | |
| 2538 | 2520 |
| 2539 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2521 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2540 context()->Plug(r0); | 2522 context()->Plug(r0); |
| 2541 } | 2523 } |
| 2542 | 2524 |
| 2543 | 2525 |
| 2544 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2526 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2545 // Assignment to a property, using a keyed store IC. | 2527 // Assignment to a property, using a keyed store IC. |
| 2546 | 2528 |
| 2547 // Record source code position before IC call. | 2529 // Record source code position before IC call. |
| 2548 SetSourcePosition(expr->position()); | 2530 SetSourcePosition(expr->position()); |
| 2549 __ Pop(r2, r1); // r1 = key. | 2531 __ Pop(r2, r1); // r1 = key. |
| 2550 | 2532 |
| 2551 Handle<Code> ic = is_classic_mode() | 2533 Handle<Code> ic = is_classic_mode() |
| 2552 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2534 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2553 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2535 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2554 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2536 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2555 | 2537 |
| 2556 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2538 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2557 context()->Plug(r0); | 2539 context()->Plug(r0); |
| 2558 } | 2540 } |
| 2559 | 2541 |
| 2560 | 2542 |
| 2561 void FullCodeGenerator::VisitProperty(Property* expr) { | 2543 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2562 Comment cmnt(masm_, "[ Property"); | 2544 Comment cmnt(masm_, "[ Property"); |
| 2563 Expression* key = expr->key(); | 2545 Expression* key = expr->key(); |
| 2564 | 2546 |
| 2565 if (key->IsPropertyName()) { | 2547 if (key->IsPropertyName()) { |
| 2566 VisitForAccumulatorValue(expr->obj()); | 2548 VisitForAccumulatorValue(expr->obj()); |
| 2567 EmitNamedPropertyLoad(expr); | 2549 EmitNamedPropertyLoad(expr); |
| 2568 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2550 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2569 context()->Plug(r0); | 2551 context()->Plug(r0); |
| 2570 } else { | 2552 } else { |
| 2571 VisitForStackValue(expr->obj()); | 2553 VisitForStackValue(expr->obj()); |
| 2572 VisitForAccumulatorValue(expr->key()); | 2554 VisitForAccumulatorValue(expr->key()); |
| 2573 __ pop(r1); | 2555 __ pop(r1); |
| 2574 EmitKeyedPropertyLoad(expr); | 2556 EmitKeyedPropertyLoad(expr); |
| 2575 context()->Plug(r0); | 2557 context()->Plug(r0); |
| 2576 } | 2558 } |
| 2577 } | 2559 } |
| 2578 | 2560 |
| 2579 | 2561 |
| 2580 void FullCodeGenerator::CallIC(Handle<Code> code, | 2562 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2581 RelocInfo::Mode rmode, | 2563 ContextualMode mode, |
| 2582 TypeFeedbackId ast_id) { | 2564 TypeFeedbackId ast_id) { |
| 2583 ic_total_count_++; | 2565 ic_total_count_++; |
| 2584 // All calls must have a predictable size in full-codegen code to ensure that | 2566 // All calls must have a predictable size in full-codegen code to ensure that |
| 2585 // the debugger can patch them correctly. | 2567 // the debugger can patch them correctly. |
| 2586 __ Call(code, rmode, ast_id, al, NEVER_INLINE_TARGET_ADDRESS); | 2568 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2569 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, |
| 2570 NEVER_INLINE_TARGET_ADDRESS); |
| 2587 } | 2571 } |
| 2588 | 2572 |
| 2589 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2573 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2590 Handle<Object> name, | 2574 Handle<Object> name, |
| 2591 RelocInfo::Mode mode) { | 2575 ContextualMode mode) { |
| 2592 // Code common for calls using the IC. | 2576 // Code common for calls using the IC. |
| 2593 ZoneList<Expression*>* args = expr->arguments(); | 2577 ZoneList<Expression*>* args = expr->arguments(); |
| 2594 int arg_count = args->length(); | 2578 int arg_count = args->length(); |
| 2595 { PreservePositionScope scope(masm()->positions_recorder()); | 2579 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2596 for (int i = 0; i < arg_count; i++) { | 2580 for (int i = 0; i < arg_count; i++) { |
| 2597 VisitForStackValue(args->at(i)); | 2581 VisitForStackValue(args->at(i)); |
| 2598 } | 2582 } |
| 2599 __ mov(r2, Operand(name)); | 2583 __ mov(r2, Operand(name)); |
| 2600 } | 2584 } |
| 2601 // Record source position for debugger. | 2585 // Record source position for debugger. |
| 2602 SetSourcePosition(expr->position()); | 2586 SetSourcePosition(expr->position()); |
| 2603 // Call the IC initialization code. | 2587 // Call the IC initialization code. |
| 2604 Handle<Code> ic = | 2588 Handle<Code> ic = |
| 2605 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2589 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2606 CallIC(ic, mode, expr->CallFeedbackId()); | 2590 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2591 ? TypeFeedbackId::None() |
| 2592 : expr->CallFeedbackId(); |
| 2593 CallIC(ic, mode, ast_id); |
| 2607 RecordJSReturnSite(expr); | 2594 RecordJSReturnSite(expr); |
| 2608 // Restore context register. | 2595 // Restore context register. |
| 2609 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2596 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2610 context()->Plug(r0); | 2597 context()->Plug(r0); |
| 2611 } | 2598 } |
| 2612 | 2599 |
| 2613 | 2600 |
| 2614 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2601 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2615 Expression* key) { | 2602 Expression* key) { |
| 2616 // Load the key. | 2603 // Load the key. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2629 for (int i = 0; i < arg_count; i++) { | 2616 for (int i = 0; i < arg_count; i++) { |
| 2630 VisitForStackValue(args->at(i)); | 2617 VisitForStackValue(args->at(i)); |
| 2631 } | 2618 } |
| 2632 } | 2619 } |
| 2633 // Record source position for debugger. | 2620 // Record source position for debugger. |
| 2634 SetSourcePosition(expr->position()); | 2621 SetSourcePosition(expr->position()); |
| 2635 // Call the IC initialization code. | 2622 // Call the IC initialization code. |
| 2636 Handle<Code> ic = | 2623 Handle<Code> ic = |
| 2637 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2624 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
| 2638 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2625 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
| 2639 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2626 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
| 2640 RecordJSReturnSite(expr); | 2627 RecordJSReturnSite(expr); |
| 2641 // Restore context register. | 2628 // Restore context register. |
| 2642 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2629 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2643 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2630 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
| 2644 } | 2631 } |
| 2645 | 2632 |
| 2646 | 2633 |
| 2647 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2634 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2648 // Code common for calls using the call stub. | 2635 // Code common for calls using the call stub. |
| 2649 ZoneList<Expression*>* args = expr->arguments(); | 2636 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2733 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2747 __ CallStub(&stub); | 2734 __ CallStub(&stub); |
| 2748 RecordJSReturnSite(expr); | 2735 RecordJSReturnSite(expr); |
| 2749 // Restore context register. | 2736 // Restore context register. |
| 2750 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2737 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2751 context()->DropAndPlug(1, r0); | 2738 context()->DropAndPlug(1, r0); |
| 2752 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2739 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 2753 // Push global object as receiver for the call IC. | 2740 // Push global object as receiver for the call IC. |
| 2754 __ ldr(r0, GlobalObjectOperand()); | 2741 __ ldr(r0, GlobalObjectOperand()); |
| 2755 __ push(r0); | 2742 __ push(r0); |
| 2756 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2743 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
| 2757 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2744 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 2758 // Call to a lookup slot (dynamically introduced variable). | 2745 // Call to a lookup slot (dynamically introduced variable). |
| 2759 Label slow, done; | 2746 Label slow, done; |
| 2760 | 2747 |
| 2761 { PreservePositionScope scope(masm()->positions_recorder()); | 2748 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2762 // Generate code for loading from variables potentially shadowed | 2749 // Generate code for loading from variables potentially shadowed |
| 2763 // by eval-introduced variables. | 2750 // by eval-introduced variables. |
| 2764 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2751 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2765 } | 2752 } |
| 2766 | 2753 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2793 // by LoadContextSlot. That object could be the hole if the | 2780 // by LoadContextSlot. That object could be the hole if the |
| 2794 // receiver is implicitly the global object. | 2781 // receiver is implicitly the global object. |
| 2795 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | 2782 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2796 } else if (property != NULL) { | 2783 } else if (property != NULL) { |
| 2797 { PreservePositionScope scope(masm()->positions_recorder()); | 2784 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2798 VisitForStackValue(property->obj()); | 2785 VisitForStackValue(property->obj()); |
| 2799 } | 2786 } |
| 2800 if (property->key()->IsPropertyName()) { | 2787 if (property->key()->IsPropertyName()) { |
| 2801 EmitCallWithIC(expr, | 2788 EmitCallWithIC(expr, |
| 2802 property->key()->AsLiteral()->value(), | 2789 property->key()->AsLiteral()->value(), |
| 2803 RelocInfo::CODE_TARGET); | 2790 NOT_CONTEXTUAL); |
| 2804 } else { | 2791 } else { |
| 2805 EmitKeyedCallWithIC(expr, property->key()); | 2792 EmitKeyedCallWithIC(expr, property->key()); |
| 2806 } | 2793 } |
| 2807 } else { | 2794 } else { |
| 2808 // Call to an arbitrary expression not handled specially above. | 2795 // Call to an arbitrary expression not handled specially above. |
| 2809 { PreservePositionScope scope(masm()->positions_recorder()); | 2796 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2810 VisitForStackValue(callee); | 2797 VisitForStackValue(callee); |
| 2811 } | 2798 } |
| 2812 // Load global receiver object. | 2799 // Load global receiver object. |
| 2813 __ ldr(r1, GlobalObjectOperand()); | 2800 __ ldr(r1, GlobalObjectOperand()); |
| (...skipping 1330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4144 | 4131 |
| 4145 // Push the arguments ("left-to-right"). | 4132 // Push the arguments ("left-to-right"). |
| 4146 int arg_count = args->length(); | 4133 int arg_count = args->length(); |
| 4147 for (int i = 0; i < arg_count; i++) { | 4134 for (int i = 0; i < arg_count; i++) { |
| 4148 VisitForStackValue(args->at(i)); | 4135 VisitForStackValue(args->at(i)); |
| 4149 } | 4136 } |
| 4150 | 4137 |
| 4151 if (expr->is_jsruntime()) { | 4138 if (expr->is_jsruntime()) { |
| 4152 // Call the JS runtime function. | 4139 // Call the JS runtime function. |
| 4153 __ mov(r2, Operand(expr->name())); | 4140 __ mov(r2, Operand(expr->name())); |
| 4154 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4141 ContextualMode mode = NOT_CONTEXTUAL; |
| 4155 Handle<Code> ic = | 4142 Handle<Code> ic = |
| 4156 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 4143 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 4157 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 4144 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
| 4158 // Restore context register. | 4145 // Restore context register. |
| 4159 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4146 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4160 } else { | 4147 } else { |
| 4161 // Call the C runtime function. | 4148 // Call the C runtime function. |
| 4162 __ CallRuntime(expr->function(), arg_count); | 4149 __ CallRuntime(expr->function(), arg_count); |
| 4163 } | 4150 } |
| 4164 context()->Plug(r0); | 4151 context()->Plug(r0); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4395 | 4382 |
| 4396 __ bind(&stub_call); | 4383 __ bind(&stub_call); |
| 4397 __ mov(r1, r0); | 4384 __ mov(r1, r0); |
| 4398 __ mov(r0, Operand(Smi::FromInt(count_value))); | 4385 __ mov(r0, Operand(Smi::FromInt(count_value))); |
| 4399 | 4386 |
| 4400 // Record position before stub call. | 4387 // Record position before stub call. |
| 4401 SetSourcePosition(expr->position()); | 4388 SetSourcePosition(expr->position()); |
| 4402 | 4389 |
| 4403 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4390 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4404 CallIC(stub.GetCode(isolate()), | 4391 CallIC(stub.GetCode(isolate()), |
| 4405 RelocInfo::CODE_TARGET, | 4392 NOT_CONTEXTUAL, |
| 4406 expr->CountBinOpFeedbackId()); | 4393 expr->CountBinOpFeedbackId()); |
| 4407 patch_site.EmitPatchInfo(); | 4394 patch_site.EmitPatchInfo(); |
| 4408 __ bind(&done); | 4395 __ bind(&done); |
| 4409 | 4396 |
| 4410 // Store the value returned in r0. | 4397 // Store the value returned in r0. |
| 4411 switch (assign_type) { | 4398 switch (assign_type) { |
| 4412 case VARIABLE: | 4399 case VARIABLE: |
| 4413 if (expr->is_postfix()) { | 4400 if (expr->is_postfix()) { |
| 4414 { EffectContext context(this); | 4401 { EffectContext context(this); |
| 4415 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4402 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4416 Token::ASSIGN); | 4403 Token::ASSIGN); |
| 4417 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4404 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4418 context.Plug(r0); | 4405 context.Plug(r0); |
| 4419 } | 4406 } |
| 4420 // For all contexts except EffectConstant We have the result on | 4407 // For all contexts except EffectConstant We have the result on |
| 4421 // top of the stack. | 4408 // top of the stack. |
| 4422 if (!context()->IsEffect()) { | 4409 if (!context()->IsEffect()) { |
| 4423 context()->PlugTOS(); | 4410 context()->PlugTOS(); |
| 4424 } | 4411 } |
| 4425 } else { | 4412 } else { |
| 4426 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4413 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4427 Token::ASSIGN); | 4414 Token::ASSIGN); |
| 4428 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4415 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4429 context()->Plug(r0); | 4416 context()->Plug(r0); |
| 4430 } | 4417 } |
| 4431 break; | 4418 break; |
| 4432 case NAMED_PROPERTY: { | 4419 case NAMED_PROPERTY: { |
| 4433 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 4420 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 4434 __ pop(r1); | 4421 __ pop(r1); |
| 4435 Handle<Code> ic = is_classic_mode() | 4422 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4436 ? isolate()->builtins()->StoreIC_Initialize() | |
| 4437 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 4438 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | |
| 4439 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4423 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4440 if (expr->is_postfix()) { | 4424 if (expr->is_postfix()) { |
| 4441 if (!context()->IsEffect()) { | 4425 if (!context()->IsEffect()) { |
| 4442 context()->PlugTOS(); | 4426 context()->PlugTOS(); |
| 4443 } | 4427 } |
| 4444 } else { | 4428 } else { |
| 4445 context()->Plug(r0); | 4429 context()->Plug(r0); |
| 4446 } | 4430 } |
| 4447 break; | 4431 break; |
| 4448 } | 4432 } |
| 4449 case KEYED_PROPERTY: { | 4433 case KEYED_PROPERTY: { |
| 4450 __ Pop(r2, r1); // r1 = key. r2 = receiver. | 4434 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4451 Handle<Code> ic = is_classic_mode() | 4435 Handle<Code> ic = is_classic_mode() |
| 4452 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4436 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4453 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4437 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4454 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4438 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4455 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4439 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4456 if (expr->is_postfix()) { | 4440 if (expr->is_postfix()) { |
| 4457 if (!context()->IsEffect()) { | 4441 if (!context()->IsEffect()) { |
| 4458 context()->PlugTOS(); | 4442 context()->PlugTOS(); |
| 4459 } | 4443 } |
| 4460 } else { | 4444 } else { |
| 4461 context()->Plug(r0); | 4445 context()->Plug(r0); |
| 4462 } | 4446 } |
| 4463 break; | 4447 break; |
| 4464 } | 4448 } |
| 4465 } | 4449 } |
| 4466 } | 4450 } |
| 4467 | 4451 |
| 4468 | 4452 |
| 4469 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4453 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4470 ASSERT(!context()->IsEffect()); | 4454 ASSERT(!context()->IsEffect()); |
| 4471 ASSERT(!context()->IsTest()); | 4455 ASSERT(!context()->IsTest()); |
| 4472 VariableProxy* proxy = expr->AsVariableProxy(); | 4456 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4473 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4457 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4474 Comment cmnt(masm_, "Global variable"); | 4458 Comment cmnt(masm_, "Global variable"); |
| 4475 __ ldr(r0, GlobalObjectOperand()); | 4459 __ ldr(r0, GlobalObjectOperand()); |
| 4476 __ mov(r2, Operand(proxy->name())); | 4460 __ mov(r2, Operand(proxy->name())); |
| 4477 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 4478 // Use a regular load, not a contextual load, to avoid a reference | 4461 // Use a regular load, not a contextual load, to avoid a reference |
| 4479 // error. | 4462 // error. |
| 4480 CallIC(ic); | 4463 CallLoadIC(NOT_CONTEXTUAL); |
| 4481 PrepareForBailout(expr, TOS_REG); | 4464 PrepareForBailout(expr, TOS_REG); |
| 4482 context()->Plug(r0); | 4465 context()->Plug(r0); |
| 4483 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4466 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4484 Label done, slow; | 4467 Label done, slow; |
| 4485 | 4468 |
| 4486 // Generate code for loading from variables potentially shadowed | 4469 // Generate code for loading from variables potentially shadowed |
| 4487 // by eval-introduced variables. | 4470 // by eval-introduced variables. |
| 4488 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4471 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4489 | 4472 |
| 4490 __ bind(&slow); | 4473 __ bind(&slow); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4635 __ orr(r2, r0, Operand(r1)); | 4618 __ orr(r2, r0, Operand(r1)); |
| 4636 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4619 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 4637 __ cmp(r1, r0); | 4620 __ cmp(r1, r0); |
| 4638 Split(cond, if_true, if_false, NULL); | 4621 Split(cond, if_true, if_false, NULL); |
| 4639 __ bind(&slow_case); | 4622 __ bind(&slow_case); |
| 4640 } | 4623 } |
| 4641 | 4624 |
| 4642 // Record position and call the compare IC. | 4625 // Record position and call the compare IC. |
| 4643 SetSourcePosition(expr->position()); | 4626 SetSourcePosition(expr->position()); |
| 4644 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4627 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4645 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4628 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4646 patch_site.EmitPatchInfo(); | 4629 patch_site.EmitPatchInfo(); |
| 4647 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4630 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4648 __ cmp(r0, Operand::Zero()); | 4631 __ cmp(r0, Operand::Zero()); |
| 4649 Split(cond, if_true, if_false, fall_through); | 4632 Split(cond, if_true, if_false, fall_through); |
| 4650 } | 4633 } |
| 4651 } | 4634 } |
| 4652 | 4635 |
| 4653 // Convert the result of the comparison into one expected for this | 4636 // Convert the result of the comparison into one expected for this |
| 4654 // expression's context. | 4637 // expression's context. |
| 4655 context()->Plug(if_true, if_false); | 4638 context()->Plug(if_true, if_false); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4670 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4653 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4671 if (expr->op() == Token::EQ_STRICT) { | 4654 if (expr->op() == Token::EQ_STRICT) { |
| 4672 Heap::RootListIndex nil_value = nil == kNullValue ? | 4655 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4673 Heap::kNullValueRootIndex : | 4656 Heap::kNullValueRootIndex : |
| 4674 Heap::kUndefinedValueRootIndex; | 4657 Heap::kUndefinedValueRootIndex; |
| 4675 __ LoadRoot(r1, nil_value); | 4658 __ LoadRoot(r1, nil_value); |
| 4676 __ cmp(r0, r1); | 4659 __ cmp(r0, r1); |
| 4677 Split(eq, if_true, if_false, fall_through); | 4660 Split(eq, if_true, if_false, fall_through); |
| 4678 } else { | 4661 } else { |
| 4679 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4662 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4680 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4663 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4681 __ cmp(r0, Operand(0)); | 4664 __ cmp(r0, Operand(0)); |
| 4682 Split(ne, if_true, if_false, fall_through); | 4665 Split(ne, if_true, if_false, fall_through); |
| 4683 } | 4666 } |
| 4684 context()->Plug(if_true, if_false); | 4667 context()->Plug(if_true, if_false); |
| 4685 } | 4668 } |
| 4686 | 4669 |
| 4687 | 4670 |
| 4688 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4671 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4689 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4672 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4690 context()->Plug(r0); | 4673 context()->Plug(r0); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4913 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4896 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4914 reinterpret_cast<uint32_t>( | 4897 reinterpret_cast<uint32_t>( |
| 4915 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4898 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4916 return OSR_AFTER_STACK_CHECK; | 4899 return OSR_AFTER_STACK_CHECK; |
| 4917 } | 4900 } |
| 4918 | 4901 |
| 4919 | 4902 |
| 4920 } } // namespace v8::internal | 4903 } } // namespace v8::internal |
| 4921 | 4904 |
| 4922 #endif // V8_TARGET_ARCH_ARM | 4905 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |