| 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 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 } | 675 } |
| 676 } | 676 } |
| 677 | 677 |
| 678 | 678 |
| 679 void FullCodeGenerator::DoTest(Expression* condition, | 679 void FullCodeGenerator::DoTest(Expression* condition, |
| 680 Label* if_true, | 680 Label* if_true, |
| 681 Label* if_false, | 681 Label* if_false, |
| 682 Label* fall_through) { | 682 Label* fall_through) { |
| 683 __ mov(a0, result_register()); | 683 __ mov(a0, result_register()); |
| 684 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 684 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 685 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); | 685 CallIC(ic, condition->test_id()); |
| 686 __ mov(at, zero_reg); | 686 __ mov(at, zero_reg); |
| 687 Split(ne, v0, Operand(at), if_true, if_false, fall_through); | 687 Split(ne, v0, Operand(at), if_true, if_false, fall_through); |
| 688 } | 688 } |
| 689 | 689 |
| 690 | 690 |
| 691 void FullCodeGenerator::Split(Condition cc, | 691 void FullCodeGenerator::Split(Condition cc, |
| 692 Register lhs, | 692 Register lhs, |
| 693 const Operand& rhs, | 693 const Operand& rhs, |
| 694 Label* if_true, | 694 Label* if_true, |
| 695 Label* if_false, | 695 Label* if_false, |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 __ Branch(&next_test, ne, a1, Operand(a0)); | 1040 __ Branch(&next_test, ne, a1, Operand(a0)); |
| 1041 __ Drop(1); // Switch value is no longer needed. | 1041 __ Drop(1); // Switch value is no longer needed. |
| 1042 __ Branch(clause->body_target()); | 1042 __ Branch(clause->body_target()); |
| 1043 | 1043 |
| 1044 __ bind(&slow_case); | 1044 __ bind(&slow_case); |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 // Record position before stub call for type feedback. | 1047 // Record position before stub call for type feedback. |
| 1048 SetSourcePosition(clause->position()); | 1048 SetSourcePosition(clause->position()); |
| 1049 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1049 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1050 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); | 1050 CallIC(ic, clause->CompareId()); |
| 1051 patch_site.EmitPatchInfo(); | 1051 patch_site.EmitPatchInfo(); |
| 1052 | 1052 |
| 1053 Label skip; | 1053 Label skip; |
| 1054 __ Branch(&skip); | 1054 __ Branch(&skip); |
| 1055 PrepareForBailout(clause, TOS_REG); | 1055 PrepareForBailout(clause, TOS_REG); |
| 1056 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 1056 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 1057 __ Branch(&next_test, ne, v0, Operand(at)); | 1057 __ Branch(&next_test, ne, v0, Operand(at)); |
| 1058 __ Drop(1); | 1058 __ Drop(1); |
| 1059 __ Branch(clause->body_target()); | 1059 __ Branch(clause->body_target()); |
| 1060 __ bind(&skip); | 1060 __ bind(&skip); |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1700 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1701 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1701 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1702 // Fall through. | 1702 // Fall through. |
| 1703 case ObjectLiteral::Property::COMPUTED: | 1703 case ObjectLiteral::Property::COMPUTED: |
| 1704 if (key->value()->IsInternalizedString()) { | 1704 if (key->value()->IsInternalizedString()) { |
| 1705 if (property->emit_store()) { | 1705 if (property->emit_store()) { |
| 1706 VisitForAccumulatorValue(value); | 1706 VisitForAccumulatorValue(value); |
| 1707 __ mov(a0, result_register()); | 1707 __ mov(a0, result_register()); |
| 1708 __ li(a2, Operand(key->value())); | 1708 __ li(a2, Operand(key->value())); |
| 1709 __ lw(a1, MemOperand(sp)); | 1709 __ lw(a1, MemOperand(sp)); |
| 1710 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); | 1710 CallStoreIC(key->LiteralFeedbackId()); |
| 1711 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1711 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1712 } else { | 1712 } else { |
| 1713 VisitForEffect(value); | 1713 VisitForEffect(value); |
| 1714 } | 1714 } |
| 1715 break; | 1715 break; |
| 1716 } | 1716 } |
| 1717 // Duplicate receiver on stack. | 1717 // Duplicate receiver on stack. |
| 1718 __ lw(a0, MemOperand(sp)); | 1718 __ lw(a0, MemOperand(sp)); |
| 1719 __ push(a0); | 1719 __ push(a0); |
| 1720 VisitForStackValue(key); | 1720 VisitForStackValue(key); |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2108 __ bind(&l_next); | 2108 __ bind(&l_next); |
| 2109 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" | 2109 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" |
| 2110 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2110 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2111 __ Push(a2, a3, a0); // "next", iter, received | 2111 __ Push(a2, a3, a0); // "next", iter, received |
| 2112 | 2112 |
| 2113 // result = receiver[f](arg); | 2113 // result = receiver[f](arg); |
| 2114 __ bind(&l_call); | 2114 __ bind(&l_call); |
| 2115 __ lw(a1, MemOperand(sp, kPointerSize)); | 2115 __ lw(a1, MemOperand(sp, kPointerSize)); |
| 2116 __ lw(a0, MemOperand(sp, 2 * kPointerSize)); | 2116 __ lw(a0, MemOperand(sp, 2 * kPointerSize)); |
| 2117 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2117 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2118 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); | 2118 CallIC(ic, TypeFeedbackId::None()); |
| 2119 __ mov(a0, v0); | 2119 __ mov(a0, v0); |
| 2120 __ mov(a1, a0); | 2120 __ mov(a1, a0); |
| 2121 __ sw(a1, MemOperand(sp, 2 * kPointerSize)); | 2121 __ sw(a1, MemOperand(sp, 2 * kPointerSize)); |
| 2122 CallFunctionStub stub(1, CALL_AS_METHOD); | 2122 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2123 __ CallStub(&stub); | 2123 __ CallStub(&stub); |
| 2124 | 2124 |
| 2125 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2125 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2126 __ Drop(1); // The function is still on the stack; drop it. | 2126 __ Drop(1); // The function is still on the stack; drop it. |
| 2127 | 2127 |
| 2128 // if (!result.done) goto l_try; | 2128 // if (!result.done) goto l_try; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 // Call load IC. It has arguments receiver and property name a0 and a2. | 2306 // Call load IC. It has arguments receiver and property name a0 and a2. |
| 2307 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2307 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2308 } | 2308 } |
| 2309 | 2309 |
| 2310 | 2310 |
| 2311 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2311 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2312 SetSourcePosition(prop->position()); | 2312 SetSourcePosition(prop->position()); |
| 2313 __ mov(a0, result_register()); | 2313 __ mov(a0, result_register()); |
| 2314 // Call keyed load IC. It has arguments key and receiver in a0 and a1. | 2314 // Call keyed load IC. It has arguments key and receiver in a0 and a1. |
| 2315 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2315 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2316 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2316 CallIC(ic, prop->PropertyFeedbackId()); |
| 2317 } | 2317 } |
| 2318 | 2318 |
| 2319 | 2319 |
| 2320 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2320 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2321 Token::Value op, | 2321 Token::Value op, |
| 2322 OverwriteMode mode, | 2322 OverwriteMode mode, |
| 2323 Expression* left_expr, | 2323 Expression* left_expr, |
| 2324 Expression* right_expr) { | 2324 Expression* right_expr) { |
| 2325 Label done, smi_case, stub_call; | 2325 Label done, smi_case, stub_call; |
| 2326 | 2326 |
| 2327 Register scratch1 = a2; | 2327 Register scratch1 = a2; |
| 2328 Register scratch2 = a3; | 2328 Register scratch2 = a3; |
| 2329 | 2329 |
| 2330 // Get the arguments. | 2330 // Get the arguments. |
| 2331 Register left = a1; | 2331 Register left = a1; |
| 2332 Register right = a0; | 2332 Register right = a0; |
| 2333 __ pop(left); | 2333 __ pop(left); |
| 2334 __ mov(a0, result_register()); | 2334 __ mov(a0, result_register()); |
| 2335 | 2335 |
| 2336 // Perform combined smi check on both operands. | 2336 // Perform combined smi check on both operands. |
| 2337 __ Or(scratch1, left, Operand(right)); | 2337 __ Or(scratch1, left, Operand(right)); |
| 2338 STATIC_ASSERT(kSmiTag == 0); | 2338 STATIC_ASSERT(kSmiTag == 0); |
| 2339 JumpPatchSite patch_site(masm_); | 2339 JumpPatchSite patch_site(masm_); |
| 2340 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2340 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2341 | 2341 |
| 2342 __ bind(&stub_call); | 2342 __ bind(&stub_call); |
| 2343 BinaryOpICStub stub(op, mode); | 2343 BinaryOpICStub stub(op, mode); |
| 2344 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2344 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2345 expr->BinaryOperationFeedbackId()); | |
| 2346 patch_site.EmitPatchInfo(); | 2345 patch_site.EmitPatchInfo(); |
| 2347 __ jmp(&done); | 2346 __ jmp(&done); |
| 2348 | 2347 |
| 2349 __ bind(&smi_case); | 2348 __ bind(&smi_case); |
| 2350 // Smi case. This code works the same way as the smi-smi case in the type | 2349 // Smi case. This code works the same way as the smi-smi case in the type |
| 2351 // recording binary operation stub, see | 2350 // recording binary operation stub, see |
| 2352 switch (op) { | 2351 switch (op) { |
| 2353 case Token::SAR: | 2352 case Token::SAR: |
| 2354 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2353 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| 2355 __ srav(right, left, scratch1); | 2354 __ srav(right, left, scratch1); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2414 } | 2413 } |
| 2415 | 2414 |
| 2416 | 2415 |
| 2417 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2416 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2418 Token::Value op, | 2417 Token::Value op, |
| 2419 OverwriteMode mode) { | 2418 OverwriteMode mode) { |
| 2420 __ mov(a0, result_register()); | 2419 __ mov(a0, result_register()); |
| 2421 __ pop(a1); | 2420 __ pop(a1); |
| 2422 BinaryOpICStub stub(op, mode); | 2421 BinaryOpICStub stub(op, mode); |
| 2423 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2422 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2424 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2423 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2425 expr->BinaryOperationFeedbackId()); | |
| 2426 patch_site.EmitPatchInfo(); | 2424 patch_site.EmitPatchInfo(); |
| 2427 context()->Plug(v0); | 2425 context()->Plug(v0); |
| 2428 } | 2426 } |
| 2429 | 2427 |
| 2430 | 2428 |
| 2431 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2429 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2432 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2430 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2433 // ReferenceError' on the left-hand side. | 2431 // ReferenceError' on the left-hand side. |
| 2434 if (!expr->IsValidLeftHandSide()) { | 2432 if (!expr->IsValidLeftHandSide()) { |
| 2435 VisitForEffect(expr); | 2433 VisitForEffect(expr); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2453 EffectContext context(this); | 2451 EffectContext context(this); |
| 2454 EmitVariableAssignment(var, Token::ASSIGN); | 2452 EmitVariableAssignment(var, Token::ASSIGN); |
| 2455 break; | 2453 break; |
| 2456 } | 2454 } |
| 2457 case NAMED_PROPERTY: { | 2455 case NAMED_PROPERTY: { |
| 2458 __ push(result_register()); // Preserve value. | 2456 __ push(result_register()); // Preserve value. |
| 2459 VisitForAccumulatorValue(prop->obj()); | 2457 VisitForAccumulatorValue(prop->obj()); |
| 2460 __ mov(a1, result_register()); | 2458 __ mov(a1, result_register()); |
| 2461 __ pop(a0); // Restore value. | 2459 __ pop(a0); // Restore value. |
| 2462 __ li(a2, Operand(prop->key()->AsLiteral()->value())); | 2460 __ li(a2, Operand(prop->key()->AsLiteral()->value())); |
| 2463 CallStoreIC(NOT_CONTEXTUAL); | 2461 CallStoreIC(); |
| 2464 break; | 2462 break; |
| 2465 } | 2463 } |
| 2466 case KEYED_PROPERTY: { | 2464 case KEYED_PROPERTY: { |
| 2467 __ push(result_register()); // Preserve value. | 2465 __ push(result_register()); // Preserve value. |
| 2468 VisitForStackValue(prop->obj()); | 2466 VisitForStackValue(prop->obj()); |
| 2469 VisitForAccumulatorValue(prop->key()); | 2467 VisitForAccumulatorValue(prop->key()); |
| 2470 __ mov(a1, result_register()); | 2468 __ mov(a1, result_register()); |
| 2471 __ Pop(a0, a2); // a0 = restored value. | 2469 __ Pop(a0, a2); // a0 = restored value. |
| 2472 Handle<Code> ic = is_classic_mode() | 2470 Handle<Code> ic = is_classic_mode() |
| 2473 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2471 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2474 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2472 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2475 CallIC(ic); | 2473 CallIC(ic); |
| 2476 break; | 2474 break; |
| 2477 } | 2475 } |
| 2478 } | 2476 } |
| 2479 context()->Plug(v0); | 2477 context()->Plug(v0); |
| 2480 } | 2478 } |
| 2481 | 2479 |
| 2482 | 2480 |
| 2483 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2481 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2484 Token::Value op) { | 2482 Token::Value op) { |
| 2485 if (var->IsUnallocated()) { | 2483 if (var->IsUnallocated()) { |
| 2486 // Global var, const, or let. | 2484 // Global var, const, or let. |
| 2487 __ mov(a0, result_register()); | 2485 __ mov(a0, result_register()); |
| 2488 __ li(a2, Operand(var->name())); | 2486 __ li(a2, Operand(var->name())); |
| 2489 __ lw(a1, GlobalObjectOperand()); | 2487 __ lw(a1, GlobalObjectOperand()); |
| 2490 CallStoreIC(CONTEXTUAL); | 2488 CallStoreIC(); |
| 2491 } else if (op == Token::INIT_CONST) { | 2489 } else if (op == Token::INIT_CONST) { |
| 2492 // Const initializers need a write barrier. | 2490 // Const initializers need a write barrier. |
| 2493 ASSERT(!var->IsParameter()); // No const parameters. | 2491 ASSERT(!var->IsParameter()); // No const parameters. |
| 2494 if (var->IsStackLocal()) { | 2492 if (var->IsStackLocal()) { |
| 2495 Label skip; | 2493 Label skip; |
| 2496 __ lw(a1, StackOperand(var)); | 2494 __ lw(a1, StackOperand(var)); |
| 2497 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2495 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2498 __ Branch(&skip, ne, a1, Operand(t0)); | 2496 __ Branch(&skip, ne, a1, Operand(t0)); |
| 2499 __ sw(result_register(), StackOperand(var)); | 2497 __ sw(result_register(), StackOperand(var)); |
| 2500 __ bind(&skip); | 2498 __ bind(&skip); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 Property* prop = expr->target()->AsProperty(); | 2573 Property* prop = expr->target()->AsProperty(); |
| 2576 ASSERT(prop != NULL); | 2574 ASSERT(prop != NULL); |
| 2577 ASSERT(prop->key()->AsLiteral() != NULL); | 2575 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2578 | 2576 |
| 2579 // Record source code position before IC call. | 2577 // Record source code position before IC call. |
| 2580 SetSourcePosition(expr->position()); | 2578 SetSourcePosition(expr->position()); |
| 2581 __ mov(a0, result_register()); // Load the value. | 2579 __ mov(a0, result_register()); // Load the value. |
| 2582 __ li(a2, Operand(prop->key()->AsLiteral()->value())); | 2580 __ li(a2, Operand(prop->key()->AsLiteral()->value())); |
| 2583 __ pop(a1); | 2581 __ pop(a1); |
| 2584 | 2582 |
| 2585 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2583 CallStoreIC(expr->AssignmentFeedbackId()); |
| 2586 | 2584 |
| 2587 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2585 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2588 context()->Plug(v0); | 2586 context()->Plug(v0); |
| 2589 } | 2587 } |
| 2590 | 2588 |
| 2591 | 2589 |
| 2592 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2590 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2593 // Assignment to a property, using a keyed store IC. | 2591 // Assignment to a property, using a keyed store IC. |
| 2594 | 2592 |
| 2595 // Record source code position before IC call. | 2593 // Record source code position before IC call. |
| 2596 SetSourcePosition(expr->position()); | 2594 SetSourcePosition(expr->position()); |
| 2597 // Call keyed store IC. | 2595 // Call keyed store IC. |
| 2598 // The arguments are: | 2596 // The arguments are: |
| 2599 // - a0 is the value, | 2597 // - a0 is the value, |
| 2600 // - a1 is the key, | 2598 // - a1 is the key, |
| 2601 // - a2 is the receiver. | 2599 // - a2 is the receiver. |
| 2602 __ mov(a0, result_register()); | 2600 __ mov(a0, result_register()); |
| 2603 __ Pop(a2, a1); // a1 = key. | 2601 __ Pop(a2, a1); // a1 = key. |
| 2604 | 2602 |
| 2605 Handle<Code> ic = is_classic_mode() | 2603 Handle<Code> ic = is_classic_mode() |
| 2606 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2604 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2607 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2605 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2608 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2606 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2609 | 2607 |
| 2610 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2608 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2611 context()->Plug(v0); | 2609 context()->Plug(v0); |
| 2612 } | 2610 } |
| 2613 | 2611 |
| 2614 | 2612 |
| 2615 void FullCodeGenerator::VisitProperty(Property* expr) { | 2613 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2616 Comment cmnt(masm_, "[ Property"); | 2614 Comment cmnt(masm_, "[ Property"); |
| 2617 Expression* key = expr->key(); | 2615 Expression* key = expr->key(); |
| 2618 | 2616 |
| 2619 if (key->IsPropertyName()) { | 2617 if (key->IsPropertyName()) { |
| 2620 VisitForAccumulatorValue(expr->obj()); | 2618 VisitForAccumulatorValue(expr->obj()); |
| 2621 EmitNamedPropertyLoad(expr); | 2619 EmitNamedPropertyLoad(expr); |
| 2622 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2620 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2623 context()->Plug(v0); | 2621 context()->Plug(v0); |
| 2624 } else { | 2622 } else { |
| 2625 VisitForStackValue(expr->obj()); | 2623 VisitForStackValue(expr->obj()); |
| 2626 VisitForAccumulatorValue(expr->key()); | 2624 VisitForAccumulatorValue(expr->key()); |
| 2627 __ pop(a1); | 2625 __ pop(a1); |
| 2628 EmitKeyedPropertyLoad(expr); | 2626 EmitKeyedPropertyLoad(expr); |
| 2629 context()->Plug(v0); | 2627 context()->Plug(v0); |
| 2630 } | 2628 } |
| 2631 } | 2629 } |
| 2632 | 2630 |
| 2633 | 2631 |
| 2634 void FullCodeGenerator::CallIC(Handle<Code> code, | 2632 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2635 ContextualMode mode, | |
| 2636 TypeFeedbackId id) { | 2633 TypeFeedbackId id) { |
| 2637 ic_total_count_++; | 2634 ic_total_count_++; |
| 2638 ASSERT(mode != CONTEXTUAL || id.IsNone()); | |
| 2639 __ Call(code, RelocInfo::CODE_TARGET, id); | 2635 __ Call(code, RelocInfo::CODE_TARGET, id); |
| 2640 } | 2636 } |
| 2641 | 2637 |
| 2642 | 2638 |
| 2643 // Code common for calls using the IC. | 2639 // Code common for calls using the IC. |
| 2644 void FullCodeGenerator::EmitCallWithIC(Call* expr) { | 2640 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
| 2645 Expression* callee = expr->expression(); | 2641 Expression* callee = expr->expression(); |
| 2646 ZoneList<Expression*>* args = expr->arguments(); | 2642 ZoneList<Expression*>* args = expr->arguments(); |
| 2647 int arg_count = args->length(); | 2643 int arg_count = args->length(); |
| 2648 | 2644 |
| (...skipping 1819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4468 } | 4464 } |
| 4469 | 4465 |
| 4470 __ bind(&stub_call); | 4466 __ bind(&stub_call); |
| 4471 __ mov(a1, v0); | 4467 __ mov(a1, v0); |
| 4472 __ li(a0, Operand(Smi::FromInt(count_value))); | 4468 __ li(a0, Operand(Smi::FromInt(count_value))); |
| 4473 | 4469 |
| 4474 // Record position before stub call. | 4470 // Record position before stub call. |
| 4475 SetSourcePosition(expr->position()); | 4471 SetSourcePosition(expr->position()); |
| 4476 | 4472 |
| 4477 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4473 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4478 CallIC(stub.GetCode(isolate()), | 4474 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId()); |
| 4479 NOT_CONTEXTUAL, | |
| 4480 expr->CountBinOpFeedbackId()); | |
| 4481 patch_site.EmitPatchInfo(); | 4475 patch_site.EmitPatchInfo(); |
| 4482 __ bind(&done); | 4476 __ bind(&done); |
| 4483 | 4477 |
| 4484 // Store the value returned in v0. | 4478 // Store the value returned in v0. |
| 4485 switch (assign_type) { | 4479 switch (assign_type) { |
| 4486 case VARIABLE: | 4480 case VARIABLE: |
| 4487 if (expr->is_postfix()) { | 4481 if (expr->is_postfix()) { |
| 4488 { EffectContext context(this); | 4482 { EffectContext context(this); |
| 4489 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4483 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4490 Token::ASSIGN); | 4484 Token::ASSIGN); |
| 4491 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4485 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4492 context.Plug(v0); | 4486 context.Plug(v0); |
| 4493 } | 4487 } |
| 4494 // For all contexts except EffectConstant we have the result on | 4488 // For all contexts except EffectConstant we have the result on |
| 4495 // top of the stack. | 4489 // top of the stack. |
| 4496 if (!context()->IsEffect()) { | 4490 if (!context()->IsEffect()) { |
| 4497 context()->PlugTOS(); | 4491 context()->PlugTOS(); |
| 4498 } | 4492 } |
| 4499 } else { | 4493 } else { |
| 4500 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4494 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4501 Token::ASSIGN); | 4495 Token::ASSIGN); |
| 4502 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4496 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4503 context()->Plug(v0); | 4497 context()->Plug(v0); |
| 4504 } | 4498 } |
| 4505 break; | 4499 break; |
| 4506 case NAMED_PROPERTY: { | 4500 case NAMED_PROPERTY: { |
| 4507 __ mov(a0, result_register()); // Value. | 4501 __ mov(a0, result_register()); // Value. |
| 4508 __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name. | 4502 __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name. |
| 4509 __ pop(a1); // Receiver. | 4503 __ pop(a1); // Receiver. |
| 4510 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4504 CallStoreIC(expr->CountStoreFeedbackId()); |
| 4511 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4505 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4512 if (expr->is_postfix()) { | 4506 if (expr->is_postfix()) { |
| 4513 if (!context()->IsEffect()) { | 4507 if (!context()->IsEffect()) { |
| 4514 context()->PlugTOS(); | 4508 context()->PlugTOS(); |
| 4515 } | 4509 } |
| 4516 } else { | 4510 } else { |
| 4517 context()->Plug(v0); | 4511 context()->Plug(v0); |
| 4518 } | 4512 } |
| 4519 break; | 4513 break; |
| 4520 } | 4514 } |
| 4521 case KEYED_PROPERTY: { | 4515 case KEYED_PROPERTY: { |
| 4522 __ mov(a0, result_register()); // Value. | 4516 __ mov(a0, result_register()); // Value. |
| 4523 __ Pop(a2, a1); // a1 = key, a2 = receiver. | 4517 __ Pop(a2, a1); // a1 = key, a2 = receiver. |
| 4524 Handle<Code> ic = is_classic_mode() | 4518 Handle<Code> ic = is_classic_mode() |
| 4525 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4519 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4526 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4520 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4527 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4521 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4528 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4522 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4529 if (expr->is_postfix()) { | 4523 if (expr->is_postfix()) { |
| 4530 if (!context()->IsEffect()) { | 4524 if (!context()->IsEffect()) { |
| 4531 context()->PlugTOS(); | 4525 context()->PlugTOS(); |
| 4532 } | 4526 } |
| 4533 } else { | 4527 } else { |
| 4534 context()->Plug(v0); | 4528 context()->Plug(v0); |
| 4535 } | 4529 } |
| 4536 break; | 4530 break; |
| 4537 } | 4531 } |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4702 if (inline_smi_code) { | 4696 if (inline_smi_code) { |
| 4703 Label slow_case; | 4697 Label slow_case; |
| 4704 __ Or(a2, a0, Operand(a1)); | 4698 __ Or(a2, a0, Operand(a1)); |
| 4705 patch_site.EmitJumpIfNotSmi(a2, &slow_case); | 4699 patch_site.EmitJumpIfNotSmi(a2, &slow_case); |
| 4706 Split(cc, a1, Operand(a0), if_true, if_false, NULL); | 4700 Split(cc, a1, Operand(a0), if_true, if_false, NULL); |
| 4707 __ bind(&slow_case); | 4701 __ bind(&slow_case); |
| 4708 } | 4702 } |
| 4709 // Record position and call the compare IC. | 4703 // Record position and call the compare IC. |
| 4710 SetSourcePosition(expr->position()); | 4704 SetSourcePosition(expr->position()); |
| 4711 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4705 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4712 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4706 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4713 patch_site.EmitPatchInfo(); | 4707 patch_site.EmitPatchInfo(); |
| 4714 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4708 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4715 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4709 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); |
| 4716 } | 4710 } |
| 4717 } | 4711 } |
| 4718 | 4712 |
| 4719 // Convert the result of the comparison into one expected for this | 4713 // Convert the result of the comparison into one expected for this |
| 4720 // expression's context. | 4714 // expression's context. |
| 4721 context()->Plug(if_true, if_false); | 4715 context()->Plug(if_true, if_false); |
| 4722 } | 4716 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4736 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4730 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4737 __ mov(a0, result_register()); | 4731 __ mov(a0, result_register()); |
| 4738 if (expr->op() == Token::EQ_STRICT) { | 4732 if (expr->op() == Token::EQ_STRICT) { |
| 4739 Heap::RootListIndex nil_value = nil == kNullValue ? | 4733 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4740 Heap::kNullValueRootIndex : | 4734 Heap::kNullValueRootIndex : |
| 4741 Heap::kUndefinedValueRootIndex; | 4735 Heap::kUndefinedValueRootIndex; |
| 4742 __ LoadRoot(a1, nil_value); | 4736 __ LoadRoot(a1, nil_value); |
| 4743 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); | 4737 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); |
| 4744 } else { | 4738 } else { |
| 4745 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4739 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4746 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4740 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4747 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4741 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through); |
| 4748 } | 4742 } |
| 4749 context()->Plug(if_true, if_false); | 4743 context()->Plug(if_true, if_false); |
| 4750 } | 4744 } |
| 4751 | 4745 |
| 4752 | 4746 |
| 4753 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4747 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4754 __ lw(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4748 __ lw(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4755 context()->Plug(v0); | 4749 context()->Plug(v0); |
| 4756 } | 4750 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4974 Assembler::target_address_at(pc_immediate_load_address)) == | 4968 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4975 reinterpret_cast<uint32_t>( | 4969 reinterpret_cast<uint32_t>( |
| 4976 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4970 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4977 return OSR_AFTER_STACK_CHECK; | 4971 return OSR_AFTER_STACK_CHECK; |
| 4978 } | 4972 } |
| 4979 | 4973 |
| 4980 | 4974 |
| 4981 } } // namespace v8::internal | 4975 } } // namespace v8::internal |
| 4982 | 4976 |
| 4983 #endif // V8_TARGET_ARCH_MIPS | 4977 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |