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 |