| 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 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 if (false_label_ != fall_through_) __ b(false_label_); | 664 if (false_label_ != fall_through_) __ b(false_label_); |
| 665 } | 665 } |
| 666 } | 666 } |
| 667 | 667 |
| 668 | 668 |
| 669 void FullCodeGenerator::DoTest(Expression* condition, | 669 void FullCodeGenerator::DoTest(Expression* condition, |
| 670 Label* if_true, | 670 Label* if_true, |
| 671 Label* if_false, | 671 Label* if_false, |
| 672 Label* fall_through) { | 672 Label* fall_through) { |
| 673 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 673 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 674 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); | 674 CallIC(ic, condition->test_id()); |
| 675 __ tst(result_register(), result_register()); | 675 __ tst(result_register(), result_register()); |
| 676 Split(ne, if_true, if_false, fall_through); | 676 Split(ne, if_true, if_false, fall_through); |
| 677 } | 677 } |
| 678 | 678 |
| 679 | 679 |
| 680 void FullCodeGenerator::Split(Condition cond, | 680 void FullCodeGenerator::Split(Condition cond, |
| 681 Label* if_true, | 681 Label* if_true, |
| 682 Label* if_false, | 682 Label* if_false, |
| 683 Label* fall_through) { | 683 Label* fall_through) { |
| 684 if (if_false == fall_through) { | 684 if (if_false == fall_through) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 __ cmp(r1, r0); | 1025 __ cmp(r1, r0); |
| 1026 __ b(ne, &next_test); | 1026 __ b(ne, &next_test); |
| 1027 __ Drop(1); // Switch value is no longer needed. | 1027 __ Drop(1); // Switch value is no longer needed. |
| 1028 __ b(clause->body_target()); | 1028 __ b(clause->body_target()); |
| 1029 __ bind(&slow_case); | 1029 __ bind(&slow_case); |
| 1030 } | 1030 } |
| 1031 | 1031 |
| 1032 // Record position before stub call for type feedback. | 1032 // Record position before stub call for type feedback. |
| 1033 SetSourcePosition(clause->position()); | 1033 SetSourcePosition(clause->position()); |
| 1034 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1034 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1035 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); | 1035 CallIC(ic, clause->CompareId()); |
| 1036 patch_site.EmitPatchInfo(); | 1036 patch_site.EmitPatchInfo(); |
| 1037 | 1037 |
| 1038 Label skip; | 1038 Label skip; |
| 1039 __ b(&skip); | 1039 __ b(&skip); |
| 1040 PrepareForBailout(clause, TOS_REG); | 1040 PrepareForBailout(clause, TOS_REG); |
| 1041 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1041 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 1042 __ cmp(r0, ip); | 1042 __ cmp(r0, ip); |
| 1043 __ b(ne, &next_test); | 1043 __ b(ne, &next_test); |
| 1044 __ Drop(1); | 1044 __ Drop(1); |
| 1045 __ jmp(clause->body_target()); | 1045 __ jmp(clause->body_target()); |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 UNREACHABLE(); | 1689 UNREACHABLE(); |
| 1690 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1690 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1691 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1691 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1692 // Fall through. | 1692 // Fall through. |
| 1693 case ObjectLiteral::Property::COMPUTED: | 1693 case ObjectLiteral::Property::COMPUTED: |
| 1694 if (key->value()->IsInternalizedString()) { | 1694 if (key->value()->IsInternalizedString()) { |
| 1695 if (property->emit_store()) { | 1695 if (property->emit_store()) { |
| 1696 VisitForAccumulatorValue(value); | 1696 VisitForAccumulatorValue(value); |
| 1697 __ mov(r2, Operand(key->value())); | 1697 __ mov(r2, Operand(key->value())); |
| 1698 __ ldr(r1, MemOperand(sp)); | 1698 __ ldr(r1, MemOperand(sp)); |
| 1699 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); | 1699 CallStoreIC(key->LiteralFeedbackId()); |
| 1700 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1700 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1701 } else { | 1701 } else { |
| 1702 VisitForEffect(value); | 1702 VisitForEffect(value); |
| 1703 } | 1703 } |
| 1704 break; | 1704 break; |
| 1705 } | 1705 } |
| 1706 // Duplicate receiver on stack. | 1706 // Duplicate receiver on stack. |
| 1707 __ ldr(r0, MemOperand(sp)); | 1707 __ ldr(r0, MemOperand(sp)); |
| 1708 __ push(r0); | 1708 __ push(r0); |
| 1709 VisitForStackValue(key); | 1709 VisitForStackValue(key); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2091 __ bind(&l_next); | 2091 __ bind(&l_next); |
| 2092 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2092 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
| 2093 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2093 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2094 __ Push(r2, r3, r0); // "next", iter, received | 2094 __ Push(r2, r3, r0); // "next", iter, received |
| 2095 | 2095 |
| 2096 // result = receiver[f](arg); | 2096 // result = receiver[f](arg); |
| 2097 __ bind(&l_call); | 2097 __ bind(&l_call); |
| 2098 __ ldr(r1, MemOperand(sp, kPointerSize)); | 2098 __ ldr(r1, MemOperand(sp, kPointerSize)); |
| 2099 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); | 2099 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); |
| 2100 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2100 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2101 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); | 2101 CallIC(ic, TypeFeedbackId::None()); |
| 2102 __ mov(r1, r0); | 2102 __ mov(r1, r0); |
| 2103 __ str(r1, MemOperand(sp, 2 * kPointerSize)); | 2103 __ str(r1, MemOperand(sp, 2 * kPointerSize)); |
| 2104 CallFunctionStub stub(1, CALL_AS_METHOD); | 2104 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2105 __ CallStub(&stub); | 2105 __ CallStub(&stub); |
| 2106 | 2106 |
| 2107 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2107 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2108 __ Drop(1); // The function is still on the stack; drop it. | 2108 __ Drop(1); // The function is still on the stack; drop it. |
| 2109 | 2109 |
| 2110 // if (!result.done) goto l_try; | 2110 // if (!result.done) goto l_try; |
| 2111 __ bind(&l_loop); | 2111 __ bind(&l_loop); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2288 __ mov(r2, Operand(key->value())); | 2288 __ mov(r2, Operand(key->value())); |
| 2289 // Call load IC. It has arguments receiver and property name r0 and r2. | 2289 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 2290 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2290 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2291 } | 2291 } |
| 2292 | 2292 |
| 2293 | 2293 |
| 2294 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2294 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2295 SetSourcePosition(prop->position()); | 2295 SetSourcePosition(prop->position()); |
| 2296 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 2296 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 2297 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2297 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2298 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2298 CallIC(ic, prop->PropertyFeedbackId()); |
| 2299 } | 2299 } |
| 2300 | 2300 |
| 2301 | 2301 |
| 2302 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2302 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2303 Token::Value op, | 2303 Token::Value op, |
| 2304 OverwriteMode mode, | 2304 OverwriteMode mode, |
| 2305 Expression* left_expr, | 2305 Expression* left_expr, |
| 2306 Expression* right_expr) { | 2306 Expression* right_expr) { |
| 2307 Label done, smi_case, stub_call; | 2307 Label done, smi_case, stub_call; |
| 2308 | 2308 |
| 2309 Register scratch1 = r2; | 2309 Register scratch1 = r2; |
| 2310 Register scratch2 = r3; | 2310 Register scratch2 = r3; |
| 2311 | 2311 |
| 2312 // Get the arguments. | 2312 // Get the arguments. |
| 2313 Register left = r1; | 2313 Register left = r1; |
| 2314 Register right = r0; | 2314 Register right = r0; |
| 2315 __ pop(left); | 2315 __ pop(left); |
| 2316 | 2316 |
| 2317 // Perform combined smi check on both operands. | 2317 // Perform combined smi check on both operands. |
| 2318 __ orr(scratch1, left, Operand(right)); | 2318 __ orr(scratch1, left, Operand(right)); |
| 2319 STATIC_ASSERT(kSmiTag == 0); | 2319 STATIC_ASSERT(kSmiTag == 0); |
| 2320 JumpPatchSite patch_site(masm_); | 2320 JumpPatchSite patch_site(masm_); |
| 2321 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2321 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2322 | 2322 |
| 2323 __ bind(&stub_call); | 2323 __ bind(&stub_call); |
| 2324 BinaryOpICStub stub(op, mode); | 2324 BinaryOpICStub stub(op, mode); |
| 2325 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2325 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2326 expr->BinaryOperationFeedbackId()); | |
| 2327 patch_site.EmitPatchInfo(); | 2326 patch_site.EmitPatchInfo(); |
| 2328 __ jmp(&done); | 2327 __ jmp(&done); |
| 2329 | 2328 |
| 2330 __ bind(&smi_case); | 2329 __ bind(&smi_case); |
| 2331 // Smi case. This code works the same way as the smi-smi case in the type | 2330 // Smi case. This code works the same way as the smi-smi case in the type |
| 2332 // recording binary operation stub, see | 2331 // recording binary operation stub, see |
| 2333 switch (op) { | 2332 switch (op) { |
| 2334 case Token::SAR: | 2333 case Token::SAR: |
| 2335 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2334 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| 2336 __ mov(right, Operand(left, ASR, scratch1)); | 2335 __ mov(right, Operand(left, ASR, scratch1)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2393 context()->Plug(r0); | 2392 context()->Plug(r0); |
| 2394 } | 2393 } |
| 2395 | 2394 |
| 2396 | 2395 |
| 2397 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2396 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2398 Token::Value op, | 2397 Token::Value op, |
| 2399 OverwriteMode mode) { | 2398 OverwriteMode mode) { |
| 2400 __ pop(r1); | 2399 __ pop(r1); |
| 2401 BinaryOpICStub stub(op, mode); | 2400 BinaryOpICStub stub(op, mode); |
| 2402 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2401 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2403 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2402 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2404 expr->BinaryOperationFeedbackId()); | |
| 2405 patch_site.EmitPatchInfo(); | 2403 patch_site.EmitPatchInfo(); |
| 2406 context()->Plug(r0); | 2404 context()->Plug(r0); |
| 2407 } | 2405 } |
| 2408 | 2406 |
| 2409 | 2407 |
| 2410 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2408 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2411 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2409 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2412 // ReferenceError' on the left-hand side. | 2410 // ReferenceError' on the left-hand side. |
| 2413 if (!expr->IsValidLeftHandSide()) { | 2411 if (!expr->IsValidLeftHandSide()) { |
| 2414 VisitForEffect(expr); | 2412 VisitForEffect(expr); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2432 EffectContext context(this); | 2430 EffectContext context(this); |
| 2433 EmitVariableAssignment(var, Token::ASSIGN); | 2431 EmitVariableAssignment(var, Token::ASSIGN); |
| 2434 break; | 2432 break; |
| 2435 } | 2433 } |
| 2436 case NAMED_PROPERTY: { | 2434 case NAMED_PROPERTY: { |
| 2437 __ push(r0); // Preserve value. | 2435 __ push(r0); // Preserve value. |
| 2438 VisitForAccumulatorValue(prop->obj()); | 2436 VisitForAccumulatorValue(prop->obj()); |
| 2439 __ mov(r1, r0); | 2437 __ mov(r1, r0); |
| 2440 __ pop(r0); // Restore value. | 2438 __ pop(r0); // Restore value. |
| 2441 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2439 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2442 CallStoreIC(NOT_CONTEXTUAL); | 2440 CallStoreIC(); |
| 2443 break; | 2441 break; |
| 2444 } | 2442 } |
| 2445 case KEYED_PROPERTY: { | 2443 case KEYED_PROPERTY: { |
| 2446 __ push(r0); // Preserve value. | 2444 __ push(r0); // Preserve value. |
| 2447 VisitForStackValue(prop->obj()); | 2445 VisitForStackValue(prop->obj()); |
| 2448 VisitForAccumulatorValue(prop->key()); | 2446 VisitForAccumulatorValue(prop->key()); |
| 2449 __ mov(r1, r0); | 2447 __ mov(r1, r0); |
| 2450 __ Pop(r0, r2); // r0 = restored value. | 2448 __ Pop(r0, r2); // r0 = restored value. |
| 2451 Handle<Code> ic = is_classic_mode() | 2449 Handle<Code> ic = is_classic_mode() |
| 2452 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2450 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2453 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2451 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2454 CallIC(ic); | 2452 CallIC(ic); |
| 2455 break; | 2453 break; |
| 2456 } | 2454 } |
| 2457 } | 2455 } |
| 2458 context()->Plug(r0); | 2456 context()->Plug(r0); |
| 2459 } | 2457 } |
| 2460 | 2458 |
| 2461 | 2459 |
| 2462 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2460 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2463 Token::Value op) { | 2461 Token::Value op) { |
| 2464 if (var->IsUnallocated()) { | 2462 if (var->IsUnallocated()) { |
| 2465 // Global var, const, or let. | 2463 // Global var, const, or let. |
| 2466 __ mov(r2, Operand(var->name())); | 2464 __ mov(r2, Operand(var->name())); |
| 2467 __ ldr(r1, GlobalObjectOperand()); | 2465 __ ldr(r1, GlobalObjectOperand()); |
| 2468 CallStoreIC(CONTEXTUAL); | 2466 CallStoreIC(); |
| 2469 } else if (op == Token::INIT_CONST) { | 2467 } else if (op == Token::INIT_CONST) { |
| 2470 // Const initializers need a write barrier. | 2468 // Const initializers need a write barrier. |
| 2471 ASSERT(!var->IsParameter()); // No const parameters. | 2469 ASSERT(!var->IsParameter()); // No const parameters. |
| 2472 if (var->IsStackLocal()) { | 2470 if (var->IsStackLocal()) { |
| 2473 __ ldr(r1, StackOperand(var)); | 2471 __ ldr(r1, StackOperand(var)); |
| 2474 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 2472 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
| 2475 __ str(result_register(), StackOperand(var), eq); | 2473 __ str(result_register(), StackOperand(var), eq); |
| 2476 } else { | 2474 } else { |
| 2477 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); | 2475 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); |
| 2478 // Like var declarations, const declarations are hoisted to function | 2476 // Like var declarations, const declarations are hoisted to function |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2552 // Assignment to a property, using a named store IC. | 2550 // Assignment to a property, using a named store IC. |
| 2553 Property* prop = expr->target()->AsProperty(); | 2551 Property* prop = expr->target()->AsProperty(); |
| 2554 ASSERT(prop != NULL); | 2552 ASSERT(prop != NULL); |
| 2555 ASSERT(prop->key()->AsLiteral() != NULL); | 2553 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2556 | 2554 |
| 2557 // Record source code position before IC call. | 2555 // Record source code position before IC call. |
| 2558 SetSourcePosition(expr->position()); | 2556 SetSourcePosition(expr->position()); |
| 2559 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2557 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2560 __ pop(r1); | 2558 __ pop(r1); |
| 2561 | 2559 |
| 2562 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2560 CallStoreIC(expr->AssignmentFeedbackId()); |
| 2563 | 2561 |
| 2564 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2562 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2565 context()->Plug(r0); | 2563 context()->Plug(r0); |
| 2566 } | 2564 } |
| 2567 | 2565 |
| 2568 | 2566 |
| 2569 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2567 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2570 // Assignment to a property, using a keyed store IC. | 2568 // Assignment to a property, using a keyed store IC. |
| 2571 | 2569 |
| 2572 // Record source code position before IC call. | 2570 // Record source code position before IC call. |
| 2573 SetSourcePosition(expr->position()); | 2571 SetSourcePosition(expr->position()); |
| 2574 __ Pop(r2, r1); // r1 = key. | 2572 __ Pop(r2, r1); // r1 = key. |
| 2575 | 2573 |
| 2576 Handle<Code> ic = is_classic_mode() | 2574 Handle<Code> ic = is_classic_mode() |
| 2577 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2575 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2578 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2576 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2579 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2577 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2580 | 2578 |
| 2581 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2579 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2582 context()->Plug(r0); | 2580 context()->Plug(r0); |
| 2583 } | 2581 } |
| 2584 | 2582 |
| 2585 | 2583 |
| 2586 void FullCodeGenerator::VisitProperty(Property* expr) { | 2584 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2587 Comment cmnt(masm_, "[ Property"); | 2585 Comment cmnt(masm_, "[ Property"); |
| 2588 Expression* key = expr->key(); | 2586 Expression* key = expr->key(); |
| 2589 | 2587 |
| 2590 if (key->IsPropertyName()) { | 2588 if (key->IsPropertyName()) { |
| 2591 VisitForAccumulatorValue(expr->obj()); | 2589 VisitForAccumulatorValue(expr->obj()); |
| 2592 EmitNamedPropertyLoad(expr); | 2590 EmitNamedPropertyLoad(expr); |
| 2593 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2591 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2594 context()->Plug(r0); | 2592 context()->Plug(r0); |
| 2595 } else { | 2593 } else { |
| 2596 VisitForStackValue(expr->obj()); | 2594 VisitForStackValue(expr->obj()); |
| 2597 VisitForAccumulatorValue(expr->key()); | 2595 VisitForAccumulatorValue(expr->key()); |
| 2598 __ pop(r1); | 2596 __ pop(r1); |
| 2599 EmitKeyedPropertyLoad(expr); | 2597 EmitKeyedPropertyLoad(expr); |
| 2600 context()->Plug(r0); | 2598 context()->Plug(r0); |
| 2601 } | 2599 } |
| 2602 } | 2600 } |
| 2603 | 2601 |
| 2604 | 2602 |
| 2605 void FullCodeGenerator::CallIC(Handle<Code> code, | 2603 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2606 ContextualMode mode, | |
| 2607 TypeFeedbackId ast_id) { | 2604 TypeFeedbackId ast_id) { |
| 2608 ic_total_count_++; | 2605 ic_total_count_++; |
| 2609 // All calls must have a predictable size in full-codegen code to ensure that | 2606 // All calls must have a predictable size in full-codegen code to ensure that |
| 2610 // the debugger can patch them correctly. | 2607 // the debugger can patch them correctly. |
| 2611 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); | |
| 2612 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, | 2608 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, |
| 2613 NEVER_INLINE_TARGET_ADDRESS); | 2609 NEVER_INLINE_TARGET_ADDRESS); |
| 2614 } | 2610 } |
| 2615 | 2611 |
| 2616 | 2612 |
| 2617 // Code common for calls using the IC. | 2613 // Code common for calls using the IC. |
| 2618 void FullCodeGenerator::EmitCallWithIC(Call* expr) { | 2614 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
| 2619 Expression* callee = expr->expression(); | 2615 Expression* callee = expr->expression(); |
| 2620 ZoneList<Expression*>* args = expr->arguments(); | 2616 ZoneList<Expression*>* args = expr->arguments(); |
| 2621 int arg_count = args->length(); | 2617 int arg_count = args->length(); |
| (...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4408 | 4404 |
| 4409 | 4405 |
| 4410 __ bind(&stub_call); | 4406 __ bind(&stub_call); |
| 4411 __ mov(r1, r0); | 4407 __ mov(r1, r0); |
| 4412 __ mov(r0, Operand(Smi::FromInt(count_value))); | 4408 __ mov(r0, Operand(Smi::FromInt(count_value))); |
| 4413 | 4409 |
| 4414 // Record position before stub call. | 4410 // Record position before stub call. |
| 4415 SetSourcePosition(expr->position()); | 4411 SetSourcePosition(expr->position()); |
| 4416 | 4412 |
| 4417 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4413 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4418 CallIC(stub.GetCode(isolate()), | 4414 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId()); |
| 4419 NOT_CONTEXTUAL, | |
| 4420 expr->CountBinOpFeedbackId()); | |
| 4421 patch_site.EmitPatchInfo(); | 4415 patch_site.EmitPatchInfo(); |
| 4422 __ bind(&done); | 4416 __ bind(&done); |
| 4423 | 4417 |
| 4424 // Store the value returned in r0. | 4418 // Store the value returned in r0. |
| 4425 switch (assign_type) { | 4419 switch (assign_type) { |
| 4426 case VARIABLE: | 4420 case VARIABLE: |
| 4427 if (expr->is_postfix()) { | 4421 if (expr->is_postfix()) { |
| 4428 { EffectContext context(this); | 4422 { EffectContext context(this); |
| 4429 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4423 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4430 Token::ASSIGN); | 4424 Token::ASSIGN); |
| 4431 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4425 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4432 context.Plug(r0); | 4426 context.Plug(r0); |
| 4433 } | 4427 } |
| 4434 // For all contexts except EffectConstant We have the result on | 4428 // For all contexts except EffectConstant We have the result on |
| 4435 // top of the stack. | 4429 // top of the stack. |
| 4436 if (!context()->IsEffect()) { | 4430 if (!context()->IsEffect()) { |
| 4437 context()->PlugTOS(); | 4431 context()->PlugTOS(); |
| 4438 } | 4432 } |
| 4439 } else { | 4433 } else { |
| 4440 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4434 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4441 Token::ASSIGN); | 4435 Token::ASSIGN); |
| 4442 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4436 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4443 context()->Plug(r0); | 4437 context()->Plug(r0); |
| 4444 } | 4438 } |
| 4445 break; | 4439 break; |
| 4446 case NAMED_PROPERTY: { | 4440 case NAMED_PROPERTY: { |
| 4447 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 4441 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 4448 __ pop(r1); | 4442 __ pop(r1); |
| 4449 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4443 CallStoreIC(expr->CountStoreFeedbackId()); |
| 4450 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4451 if (expr->is_postfix()) { | 4445 if (expr->is_postfix()) { |
| 4452 if (!context()->IsEffect()) { | 4446 if (!context()->IsEffect()) { |
| 4453 context()->PlugTOS(); | 4447 context()->PlugTOS(); |
| 4454 } | 4448 } |
| 4455 } else { | 4449 } else { |
| 4456 context()->Plug(r0); | 4450 context()->Plug(r0); |
| 4457 } | 4451 } |
| 4458 break; | 4452 break; |
| 4459 } | 4453 } |
| 4460 case KEYED_PROPERTY: { | 4454 case KEYED_PROPERTY: { |
| 4461 __ Pop(r2, r1); // r1 = key. r2 = receiver. | 4455 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4462 Handle<Code> ic = is_classic_mode() | 4456 Handle<Code> ic = is_classic_mode() |
| 4463 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4457 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4464 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4458 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4465 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4459 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4466 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4460 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4467 if (expr->is_postfix()) { | 4461 if (expr->is_postfix()) { |
| 4468 if (!context()->IsEffect()) { | 4462 if (!context()->IsEffect()) { |
| 4469 context()->PlugTOS(); | 4463 context()->PlugTOS(); |
| 4470 } | 4464 } |
| 4471 } else { | 4465 } else { |
| 4472 context()->Plug(r0); | 4466 context()->Plug(r0); |
| 4473 } | 4467 } |
| 4474 break; | 4468 break; |
| 4475 } | 4469 } |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4645 __ orr(r2, r0, Operand(r1)); | 4639 __ orr(r2, r0, Operand(r1)); |
| 4646 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4640 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 4647 __ cmp(r1, r0); | 4641 __ cmp(r1, r0); |
| 4648 Split(cond, if_true, if_false, NULL); | 4642 Split(cond, if_true, if_false, NULL); |
| 4649 __ bind(&slow_case); | 4643 __ bind(&slow_case); |
| 4650 } | 4644 } |
| 4651 | 4645 |
| 4652 // Record position and call the compare IC. | 4646 // Record position and call the compare IC. |
| 4653 SetSourcePosition(expr->position()); | 4647 SetSourcePosition(expr->position()); |
| 4654 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4648 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4655 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4649 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4656 patch_site.EmitPatchInfo(); | 4650 patch_site.EmitPatchInfo(); |
| 4657 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4651 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4658 __ cmp(r0, Operand::Zero()); | 4652 __ cmp(r0, Operand::Zero()); |
| 4659 Split(cond, if_true, if_false, fall_through); | 4653 Split(cond, if_true, if_false, fall_through); |
| 4660 } | 4654 } |
| 4661 } | 4655 } |
| 4662 | 4656 |
| 4663 // Convert the result of the comparison into one expected for this | 4657 // Convert the result of the comparison into one expected for this |
| 4664 // expression's context. | 4658 // expression's context. |
| 4665 context()->Plug(if_true, if_false); | 4659 context()->Plug(if_true, if_false); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4680 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4674 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4681 if (expr->op() == Token::EQ_STRICT) { | 4675 if (expr->op() == Token::EQ_STRICT) { |
| 4682 Heap::RootListIndex nil_value = nil == kNullValue ? | 4676 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4683 Heap::kNullValueRootIndex : | 4677 Heap::kNullValueRootIndex : |
| 4684 Heap::kUndefinedValueRootIndex; | 4678 Heap::kUndefinedValueRootIndex; |
| 4685 __ LoadRoot(r1, nil_value); | 4679 __ LoadRoot(r1, nil_value); |
| 4686 __ cmp(r0, r1); | 4680 __ cmp(r0, r1); |
| 4687 Split(eq, if_true, if_false, fall_through); | 4681 Split(eq, if_true, if_false, fall_through); |
| 4688 } else { | 4682 } else { |
| 4689 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4683 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4690 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4684 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4691 __ cmp(r0, Operand(0)); | 4685 __ cmp(r0, Operand(0)); |
| 4692 Split(ne, if_true, if_false, fall_through); | 4686 Split(ne, if_true, if_false, fall_through); |
| 4693 } | 4687 } |
| 4694 context()->Plug(if_true, if_false); | 4688 context()->Plug(if_true, if_false); |
| 4695 } | 4689 } |
| 4696 | 4690 |
| 4697 | 4691 |
| 4698 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4692 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4699 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4693 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4700 context()->Plug(r0); | 4694 context()->Plug(r0); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4923 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4917 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4924 reinterpret_cast<uint32_t>( | 4918 reinterpret_cast<uint32_t>( |
| 4925 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4919 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4926 return OSR_AFTER_STACK_CHECK; | 4920 return OSR_AFTER_STACK_CHECK; |
| 4927 } | 4921 } |
| 4928 | 4922 |
| 4929 | 4923 |
| 4930 } } // namespace v8::internal | 4924 } } // namespace v8::internal |
| 4931 | 4925 |
| 4932 #endif // V8_TARGET_ARCH_ARM | 4926 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |