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 2027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2038 | 2038 |
2039 // receiver = iter; f = iter.next; arg = received; | 2039 // receiver = iter; f = iter.next; arg = received; |
2040 __ bind(&l_next); | 2040 __ bind(&l_next); |
2041 __ mov(ecx, isolate()->factory()->next_string()); // "next" | 2041 __ mov(ecx, isolate()->factory()->next_string()); // "next" |
2042 __ push(ecx); | 2042 __ push(ecx); |
2043 __ push(Operand(esp, 2 * kPointerSize)); // iter | 2043 __ push(Operand(esp, 2 * kPointerSize)); // iter |
2044 __ push(eax); // received | 2044 __ push(eax); // received |
2045 | 2045 |
2046 // result = receiver[f](arg); | 2046 // result = receiver[f](arg); |
2047 __ bind(&l_call); | 2047 __ bind(&l_call); |
2048 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2048 __ mov(edx, Operand(esp, kPointerSize)); |
2049 CallIC(ic); | 2049 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2050 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); |
| 2051 __ mov(edi, eax); |
| 2052 __ mov(Operand(esp, 2 * kPointerSize), edi); |
| 2053 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2054 __ CallStub(&stub); |
| 2055 |
2050 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2056 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2051 __ Drop(1); // The key is still on the stack; drop it. | 2057 __ Drop(1); // The function is still on the stack; drop it. |
2052 | 2058 |
2053 // if (!result.done) goto l_try; | 2059 // if (!result.done) goto l_try; |
2054 __ bind(&l_loop); | 2060 __ bind(&l_loop); |
2055 __ push(eax); // save result | 2061 __ push(eax); // save result |
2056 __ mov(edx, eax); // result | 2062 __ mov(edx, eax); // result |
2057 __ mov(ecx, isolate()->factory()->done_string()); // "done" | 2063 __ mov(ecx, isolate()->factory()->done_string()); // "done" |
2058 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax | 2064 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax |
2059 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2065 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
2060 CallIC(bool_ic); | 2066 CallIC(bool_ic); |
2061 __ test(eax, eax); | 2067 __ test(eax, eax); |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2549 ContextualMode mode, | 2555 ContextualMode mode, |
2550 TypeFeedbackId ast_id) { | 2556 TypeFeedbackId ast_id) { |
2551 ic_total_count_++; | 2557 ic_total_count_++; |
2552 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); | 2558 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
2553 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2559 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
2554 } | 2560 } |
2555 | 2561 |
2556 | 2562 |
2557 | 2563 |
2558 | 2564 |
2559 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2565 // Code common for calls using the IC. |
2560 Handle<Object> name, | 2566 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
2561 ContextualMode mode) { | 2567 Expression* callee = expr->expression(); |
2562 // Code common for calls using the IC. | |
2563 ZoneList<Expression*>* args = expr->arguments(); | 2568 ZoneList<Expression*>* args = expr->arguments(); |
2564 int arg_count = args->length(); | 2569 int arg_count = args->length(); |
| 2570 |
| 2571 CallFunctionFlags flags; |
| 2572 // Get the target function. |
| 2573 if (callee->IsVariableProxy()) { |
| 2574 { StackValueContext context(this); |
| 2575 EmitVariableLoad(callee->AsVariableProxy()); |
| 2576 PrepareForBailout(callee, NO_REGISTERS); |
| 2577 } |
| 2578 // Push undefined as receiver. This is patched in the method prologue if it |
| 2579 // is a classic mode method. |
| 2580 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2581 flags = NO_CALL_FUNCTION_FLAGS; |
| 2582 } else { |
| 2583 // Load the function from the receiver. |
| 2584 ASSERT(callee->IsProperty()); |
| 2585 __ mov(edx, Operand(esp, 0)); |
| 2586 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2587 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2588 // Push the target function under the receiver. |
| 2589 __ push(Operand(esp, 0)); |
| 2590 __ mov(Operand(esp, kPointerSize), eax); |
| 2591 flags = CALL_AS_METHOD; |
| 2592 } |
| 2593 |
| 2594 // Load the arguments. |
2565 { PreservePositionScope scope(masm()->positions_recorder()); | 2595 { PreservePositionScope scope(masm()->positions_recorder()); |
2566 for (int i = 0; i < arg_count; i++) { | 2596 for (int i = 0; i < arg_count; i++) { |
2567 VisitForStackValue(args->at(i)); | 2597 VisitForStackValue(args->at(i)); |
2568 } | 2598 } |
2569 __ Set(ecx, Immediate(name)); | |
2570 } | 2599 } |
| 2600 |
2571 // Record source position of the IC call. | 2601 // Record source position of the IC call. |
2572 SetSourcePosition(expr->position()); | 2602 SetSourcePosition(expr->position()); |
2573 Handle<Code> ic = | 2603 CallFunctionStub stub(arg_count, flags); |
2574 isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 2604 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2575 TypeFeedbackId ast_id = mode == CONTEXTUAL | 2605 __ CallStub(&stub); |
2576 ? TypeFeedbackId::None() | |
2577 : expr->CallFeedbackId(); | |
2578 CallIC(ic, mode, ast_id); | |
2579 RecordJSReturnSite(expr); | 2606 RecordJSReturnSite(expr); |
| 2607 |
2580 // Restore context register. | 2608 // Restore context register. |
2581 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2609 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2582 context()->Plug(eax); | 2610 |
| 2611 context()->DropAndPlug(1, eax); |
2583 } | 2612 } |
2584 | 2613 |
2585 | 2614 |
| 2615 // Code common for calls using the IC. |
2586 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2616 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2587 Expression* key) { | 2617 Expression* key) { |
2588 // Load the key. | 2618 // Load the key. |
2589 VisitForAccumulatorValue(key); | 2619 VisitForAccumulatorValue(key); |
2590 | 2620 |
2591 // Swap the name of the function and the receiver on the stack to follow | 2621 Expression* callee = expr->expression(); |
2592 // the calling convention for call ICs. | 2622 ZoneList<Expression*>* args = expr->arguments(); |
2593 __ pop(ecx); | 2623 int arg_count = args->length(); |
2594 __ push(eax); | 2624 |
2595 __ push(ecx); | 2625 // Load the function from the receiver. |
| 2626 ASSERT(callee->IsProperty()); |
| 2627 __ mov(edx, Operand(esp, 0)); |
| 2628 // Move the key into the right register for the keyed load IC. |
| 2629 __ mov(ecx, eax); |
| 2630 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2631 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2632 |
| 2633 // Push the target function under the receiver. |
| 2634 __ push(Operand(esp, 0)); |
| 2635 __ mov(Operand(esp, kPointerSize), eax); |
2596 | 2636 |
2597 // Load the arguments. | 2637 // Load the arguments. |
2598 ZoneList<Expression*>* args = expr->arguments(); | |
2599 int arg_count = args->length(); | |
2600 { PreservePositionScope scope(masm()->positions_recorder()); | 2638 { PreservePositionScope scope(masm()->positions_recorder()); |
2601 for (int i = 0; i < arg_count; i++) { | 2639 for (int i = 0; i < arg_count; i++) { |
2602 VisitForStackValue(args->at(i)); | 2640 VisitForStackValue(args->at(i)); |
2603 } | 2641 } |
2604 } | 2642 } |
| 2643 |
2605 // Record source position of the IC call. | 2644 // Record source position of the IC call. |
2606 SetSourcePosition(expr->position()); | 2645 SetSourcePosition(expr->position()); |
2607 Handle<Code> ic = | 2646 CallFunctionStub stub(arg_count, CALL_AS_METHOD); |
2608 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2647 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2609 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2648 __ CallStub(&stub); |
2610 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); | |
2611 RecordJSReturnSite(expr); | 2649 RecordJSReturnSite(expr); |
| 2650 |
2612 // Restore context register. | 2651 // Restore context register. |
2613 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2652 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2614 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2653 |
| 2654 context()->DropAndPlug(1, eax); |
2615 } | 2655 } |
2616 | 2656 |
2617 | 2657 |
2618 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2658 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
2619 // Code common for calls using the call stub. | 2659 // Code common for calls using the call stub. |
2620 ZoneList<Expression*>* args = expr->arguments(); | 2660 ZoneList<Expression*>* args = expr->arguments(); |
2621 int arg_count = args->length(); | 2661 int arg_count = args->length(); |
2622 { PreservePositionScope scope(masm()->positions_recorder()); | 2662 { PreservePositionScope scope(masm()->positions_recorder()); |
2623 for (int i = 0; i < arg_count; i++) { | 2663 for (int i = 0; i < arg_count; i++) { |
2624 VisitForStackValue(args->at(i)); | 2664 VisitForStackValue(args->at(i)); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2706 SetSourcePosition(expr->position()); | 2746 SetSourcePosition(expr->position()); |
2707 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); | 2747 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
2708 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2748 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2709 __ CallStub(&stub); | 2749 __ CallStub(&stub); |
2710 RecordJSReturnSite(expr); | 2750 RecordJSReturnSite(expr); |
2711 // Restore context register. | 2751 // Restore context register. |
2712 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2752 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2713 context()->DropAndPlug(1, eax); | 2753 context()->DropAndPlug(1, eax); |
2714 | 2754 |
2715 } else if (call_type == Call::GLOBAL_CALL) { | 2755 } else if (call_type == Call::GLOBAL_CALL) { |
2716 // Push global object as receiver for the call IC. | 2756 EmitCallWithIC(expr); |
2717 __ push(GlobalObjectOperand()); | 2757 |
2718 VariableProxy* proxy = callee->AsVariableProxy(); | |
2719 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); | |
2720 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2758 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
2721 // Call to a lookup slot (dynamically introduced variable). | 2759 // Call to a lookup slot (dynamically introduced variable). |
2722 VariableProxy* proxy = callee->AsVariableProxy(); | 2760 VariableProxy* proxy = callee->AsVariableProxy(); |
2723 Label slow, done; | 2761 Label slow, done; |
2724 { PreservePositionScope scope(masm()->positions_recorder()); | 2762 { PreservePositionScope scope(masm()->positions_recorder()); |
2725 // Generate code for loading from variables potentially shadowed by | 2763 // Generate code for loading from variables potentially shadowed by |
2726 // eval-introduced variables. | 2764 // eval-introduced variables. |
2727 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2765 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
2728 } | 2766 } |
2729 __ bind(&slow); | 2767 __ bind(&slow); |
(...skipping 22 matching lines...) Expand all Loading... |
2752 // The receiver is either the global receiver or an object found by | 2790 // The receiver is either the global receiver or an object found by |
2753 // LoadContextSlot. | 2791 // LoadContextSlot. |
2754 EmitCallWithStub(expr); | 2792 EmitCallWithStub(expr); |
2755 | 2793 |
2756 } else if (call_type == Call::PROPERTY_CALL) { | 2794 } else if (call_type == Call::PROPERTY_CALL) { |
2757 Property* property = callee->AsProperty(); | 2795 Property* property = callee->AsProperty(); |
2758 { PreservePositionScope scope(masm()->positions_recorder()); | 2796 { PreservePositionScope scope(masm()->positions_recorder()); |
2759 VisitForStackValue(property->obj()); | 2797 VisitForStackValue(property->obj()); |
2760 } | 2798 } |
2761 if (property->key()->IsPropertyName()) { | 2799 if (property->key()->IsPropertyName()) { |
2762 EmitCallWithIC(expr, | 2800 EmitCallWithIC(expr); |
2763 property->key()->AsLiteral()->value(), | |
2764 NOT_CONTEXTUAL); | |
2765 } else { | 2801 } else { |
2766 EmitKeyedCallWithIC(expr, property->key()); | 2802 EmitKeyedCallWithIC(expr, property->key()); |
2767 } | 2803 } |
2768 | 2804 |
2769 } else { | 2805 } else { |
2770 ASSERT(call_type == Call::OTHER_CALL); | 2806 ASSERT(call_type == Call::OTHER_CALL); |
2771 // Call to an arbitrary expression not handled specially above. | 2807 // Call to an arbitrary expression not handled specially above. |
2772 { PreservePositionScope scope(masm()->positions_recorder()); | 2808 { PreservePositionScope scope(masm()->positions_recorder()); |
2773 VisitForStackValue(callee); | 2809 VisitForStackValue(callee); |
2774 } | 2810 } |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4084 if (name->length() > 0 && name->Get(0) == '_') { | 4120 if (name->length() > 0 && name->Get(0) == '_') { |
4085 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 4121 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
4086 EmitInlineRuntimeCall(expr); | 4122 EmitInlineRuntimeCall(expr); |
4087 return; | 4123 return; |
4088 } | 4124 } |
4089 | 4125 |
4090 Comment cmnt(masm_, "[ CallRuntime"); | 4126 Comment cmnt(masm_, "[ CallRuntime"); |
4091 ZoneList<Expression*>* args = expr->arguments(); | 4127 ZoneList<Expression*>* args = expr->arguments(); |
4092 | 4128 |
4093 if (expr->is_jsruntime()) { | 4129 if (expr->is_jsruntime()) { |
4094 // Prepare for calling JS runtime function. | 4130 // Push the builtins object as receiver. |
4095 __ mov(eax, GlobalObjectOperand()); | 4131 __ mov(eax, GlobalObjectOperand()); |
4096 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 4132 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
4097 } | |
4098 | 4133 |
4099 // Push the arguments ("left-to-right"). | 4134 // Load the function from the receiver. |
4100 int arg_count = args->length(); | 4135 __ mov(edx, Operand(esp, 0)); |
4101 for (int i = 0; i < arg_count; i++) { | 4136 __ mov(ecx, Immediate(expr->name())); |
4102 VisitForStackValue(args->at(i)); | 4137 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
4103 } | |
4104 | 4138 |
4105 if (expr->is_jsruntime()) { | 4139 // Push the target function under the receiver. |
4106 // Call the JS runtime function via a call IC. | 4140 __ push(Operand(esp, 0)); |
4107 __ Set(ecx, Immediate(expr->name())); | 4141 __ mov(Operand(esp, kPointerSize), eax); |
4108 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 4142 |
4109 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 4143 // Code common for calls using the IC. |
| 4144 ZoneList<Expression*>* args = expr->arguments(); |
| 4145 int arg_count = args->length(); |
| 4146 for (int i = 0; i < arg_count; i++) { |
| 4147 VisitForStackValue(args->at(i)); |
| 4148 } |
| 4149 |
| 4150 // Record source position of the IC call. |
| 4151 SetSourcePosition(expr->position()); |
| 4152 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 4153 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 4154 __ CallStub(&stub); |
4110 // Restore context register. | 4155 // Restore context register. |
4111 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4156 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4157 context()->DropAndPlug(1, eax); |
| 4158 |
4112 } else { | 4159 } else { |
| 4160 // Push the arguments ("left-to-right"). |
| 4161 int arg_count = args->length(); |
| 4162 for (int i = 0; i < arg_count; i++) { |
| 4163 VisitForStackValue(args->at(i)); |
| 4164 } |
| 4165 |
4113 // Call the C runtime function. | 4166 // Call the C runtime function. |
4114 __ CallRuntime(expr->function(), arg_count); | 4167 __ CallRuntime(expr->function(), arg_count); |
| 4168 |
| 4169 context()->Plug(eax); |
4115 } | 4170 } |
4116 context()->Plug(eax); | |
4117 } | 4171 } |
4118 | 4172 |
4119 | 4173 |
4120 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4174 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
4121 switch (expr->op()) { | 4175 switch (expr->op()) { |
4122 case Token::DELETE: { | 4176 case Token::DELETE: { |
4123 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4177 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4124 Property* property = expr->expression()->AsProperty(); | 4178 Property* property = expr->expression()->AsProperty(); |
4125 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4179 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4126 | 4180 |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4858 | 4912 |
4859 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4860 Assembler::target_address_at(call_target_address)); | 4914 Assembler::target_address_at(call_target_address)); |
4861 return OSR_AFTER_STACK_CHECK; | 4915 return OSR_AFTER_STACK_CHECK; |
4862 } | 4916 } |
4863 | 4917 |
4864 | 4918 |
4865 } } // namespace v8::internal | 4919 } } // namespace v8::internal |
4866 | 4920 |
4867 #endif // V8_TARGET_ARCH_IA32 | 4921 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |