| 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 2031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2042 | 2042 |
| 2043 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 2043 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
| 2044 Label l_next, l_call, l_loop; | 2044 Label l_next, l_call, l_loop; |
| 2045 // Initial send value is undefined. | 2045 // Initial send value is undefined. |
| 2046 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2046 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 2047 __ b(&l_next); | 2047 __ b(&l_next); |
| 2048 | 2048 |
| 2049 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2049 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 2050 __ bind(&l_catch); | 2050 __ bind(&l_catch); |
| 2051 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2051 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 2052 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" | 2052 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" |
| 2053 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2053 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2054 __ Push(r3, r0); // iter, exception | 2054 __ Push(r2, r3, r0); // "throw", iter, except |
| 2055 __ jmp(&l_call); | 2055 __ jmp(&l_call); |
| 2056 | 2056 |
| 2057 // try { received = %yield result } | 2057 // try { received = %yield result } |
| 2058 // Shuffle the received result above a try handler and yield it without | 2058 // Shuffle the received result above a try handler and yield it without |
| 2059 // re-boxing. | 2059 // re-boxing. |
| 2060 __ bind(&l_try); | 2060 __ bind(&l_try); |
| 2061 __ pop(r0); // result | 2061 __ pop(r0); // result |
| 2062 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2062 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 2063 const int handler_size = StackHandlerConstants::kSize; | 2063 const int handler_size = StackHandlerConstants::kSize; |
| 2064 __ push(r0); // result | 2064 __ push(r0); // result |
| 2065 __ jmp(&l_suspend); | 2065 __ jmp(&l_suspend); |
| 2066 __ bind(&l_continuation); | 2066 __ bind(&l_continuation); |
| 2067 __ jmp(&l_resume); | 2067 __ jmp(&l_resume); |
| 2068 __ bind(&l_suspend); | 2068 __ bind(&l_suspend); |
| 2069 const int generator_object_depth = kPointerSize + handler_size; | 2069 const int generator_object_depth = kPointerSize + handler_size; |
| 2070 __ ldr(r0, MemOperand(sp, generator_object_depth)); | 2070 __ ldr(r0, MemOperand(sp, generator_object_depth)); |
| 2071 __ push(r0); // g | 2071 __ push(r0); // g |
| 2072 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2072 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 2073 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); | 2073 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); |
| 2074 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 2074 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
| 2075 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 2075 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
| 2076 __ mov(r1, cp); | 2076 __ mov(r1, cp); |
| 2077 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 2077 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
| 2078 kLRHasBeenSaved, kDontSaveFPRegs); | 2078 kLRHasBeenSaved, kDontSaveFPRegs); |
| 2079 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2079 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 2080 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2080 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2081 __ pop(r0); // result | 2081 __ pop(r0); // result |
| 2082 EmitReturnSequence(); | 2082 EmitReturnSequence(); |
| 2083 __ bind(&l_resume); // received in r0 | 2083 __ bind(&l_resume); // received in r0 |
| 2084 __ PopTryHandler(); | 2084 __ PopTryHandler(); |
| 2085 | 2085 |
| 2086 // receiver = iter; f = 'next'; arg = received; | 2086 // receiver = iter; f = 'next'; arg = received; |
| 2087 __ bind(&l_next); | 2087 __ bind(&l_next); |
| 2088 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2088 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
| 2089 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2089 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2090 __ Push(r3, r0); // iter, received | 2090 __ Push(r2, r3, r0); // "next", iter, received |
| 2091 | 2091 |
| 2092 // result = receiver[f](arg); | 2092 // result = receiver[f](arg); |
| 2093 __ bind(&l_call); | 2093 __ bind(&l_call); |
| 2094 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2094 __ ldr(r1, MemOperand(sp, kPointerSize)); |
| 2095 CallIC(ic); | 2095 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); |
| 2096 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2097 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); |
| 2098 __ mov(r1, r0); |
| 2099 __ str(r1, MemOperand(sp, 2 * kPointerSize)); |
| 2100 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2101 __ CallStub(&stub); |
| 2102 |
| 2096 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2103 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2104 __ Drop(1); // The function is still on the stack; drop it. |
| 2097 | 2105 |
| 2098 // if (!result.done) goto l_try; | 2106 // if (!result.done) goto l_try; |
| 2099 __ bind(&l_loop); | 2107 __ bind(&l_loop); |
| 2100 __ push(r0); // save result | 2108 __ push(r0); // save result |
| 2101 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" | 2109 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" |
| 2102 CallLoadIC(NOT_CONTEXTUAL); // result.done in r0 | 2110 CallLoadIC(NOT_CONTEXTUAL); // result.done in r0 |
| 2103 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2111 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2104 CallIC(bool_ic); | 2112 CallIC(bool_ic); |
| 2105 __ cmp(r0, Operand(0)); | 2113 __ cmp(r0, Operand(0)); |
| 2106 __ b(eq, &l_try); | 2114 __ b(eq, &l_try); |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 ContextualMode mode, | 2602 ContextualMode mode, |
| 2595 TypeFeedbackId ast_id) { | 2603 TypeFeedbackId ast_id) { |
| 2596 ic_total_count_++; | 2604 ic_total_count_++; |
| 2597 // All calls must have a predictable size in full-codegen code to ensure that | 2605 // All calls must have a predictable size in full-codegen code to ensure that |
| 2598 // the debugger can patch them correctly. | 2606 // the debugger can patch them correctly. |
| 2599 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); | 2607 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2600 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, | 2608 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, |
| 2601 NEVER_INLINE_TARGET_ADDRESS); | 2609 NEVER_INLINE_TARGET_ADDRESS); |
| 2602 } | 2610 } |
| 2603 | 2611 |
| 2604 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2612 |
| 2605 Handle<Object> name, | 2613 // Code common for calls using the IC. |
| 2606 ContextualMode mode) { | 2614 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
| 2607 // Code common for calls using the IC. | 2615 Expression* callee = expr->expression(); |
| 2608 ZoneList<Expression*>* args = expr->arguments(); | 2616 ZoneList<Expression*>* args = expr->arguments(); |
| 2609 int arg_count = args->length(); | 2617 int arg_count = args->length(); |
| 2618 |
| 2619 CallFunctionFlags flags; |
| 2620 // Get the target function. |
| 2621 if (callee->IsVariableProxy()) { |
| 2622 { StackValueContext context(this); |
| 2623 EmitVariableLoad(callee->AsVariableProxy()); |
| 2624 PrepareForBailout(callee, NO_REGISTERS); |
| 2625 } |
| 2626 // Push undefined as receiver. This is patched in the method prologue if it |
| 2627 // is a classic mode method. |
| 2628 __ Push(isolate()->factory()->undefined_value()); |
| 2629 flags = NO_CALL_FUNCTION_FLAGS; |
| 2630 } else { |
| 2631 // Load the function from the receiver. |
| 2632 ASSERT(callee->IsProperty()); |
| 2633 __ ldr(r0, MemOperand(sp, 0)); |
| 2634 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2635 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2636 // Push the target function under the receiver. |
| 2637 __ ldr(ip, MemOperand(sp, 0)); |
| 2638 __ push(ip); |
| 2639 __ str(r0, MemOperand(sp, kPointerSize)); |
| 2640 flags = CALL_AS_METHOD; |
| 2641 } |
| 2642 |
| 2643 // Load the arguments. |
| 2610 { PreservePositionScope scope(masm()->positions_recorder()); | 2644 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2611 for (int i = 0; i < arg_count; i++) { | 2645 for (int i = 0; i < arg_count; i++) { |
| 2612 VisitForStackValue(args->at(i)); | 2646 VisitForStackValue(args->at(i)); |
| 2613 } | 2647 } |
| 2614 __ mov(r2, Operand(name)); | |
| 2615 } | 2648 } |
| 2649 |
| 2616 // Record source position for debugger. | 2650 // Record source position for debugger. |
| 2617 SetSourcePosition(expr->position()); | 2651 SetSourcePosition(expr->position()); |
| 2618 // Call the IC initialization code. | 2652 CallFunctionStub stub(arg_count, flags); |
| 2619 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 2653 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2620 TypeFeedbackId ast_id = mode == CONTEXTUAL | 2654 __ CallStub(&stub); |
| 2621 ? TypeFeedbackId::None() | 2655 |
| 2622 : expr->CallFeedbackId(); | |
| 2623 CallIC(ic, mode, ast_id); | |
| 2624 RecordJSReturnSite(expr); | 2656 RecordJSReturnSite(expr); |
| 2657 |
| 2625 // Restore context register. | 2658 // Restore context register. |
| 2626 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2659 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2627 context()->Plug(r0); | 2660 |
| 2661 context()->DropAndPlug(1, r0); |
| 2628 } | 2662 } |
| 2629 | 2663 |
| 2630 | 2664 |
| 2665 // Code common for calls using the IC. |
| 2631 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2666 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2632 Expression* key) { | 2667 Expression* key) { |
| 2633 // Load the key. | 2668 // Load the key. |
| 2634 VisitForAccumulatorValue(key); | 2669 VisitForAccumulatorValue(key); |
| 2635 | 2670 |
| 2636 // Swap the name of the function and the receiver on the stack to follow | 2671 Expression* callee = expr->expression(); |
| 2637 // the calling convention for call ICs. | |
| 2638 __ pop(r1); | |
| 2639 __ push(r0); | |
| 2640 __ push(r1); | |
| 2641 | |
| 2642 // Code common for calls using the IC. | |
| 2643 ZoneList<Expression*>* args = expr->arguments(); | 2672 ZoneList<Expression*>* args = expr->arguments(); |
| 2644 int arg_count = args->length(); | 2673 int arg_count = args->length(); |
| 2674 |
| 2675 // Load the function from the receiver. |
| 2676 ASSERT(callee->IsProperty()); |
| 2677 __ ldr(r1, MemOperand(sp, 0)); |
| 2678 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2679 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2680 |
| 2681 // Push the target function under the receiver. |
| 2682 __ ldr(ip, MemOperand(sp, 0)); |
| 2683 __ push(ip); |
| 2684 __ str(r0, MemOperand(sp, kPointerSize)); |
| 2685 |
| 2645 { PreservePositionScope scope(masm()->positions_recorder()); | 2686 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2646 for (int i = 0; i < arg_count; i++) { | 2687 for (int i = 0; i < arg_count; i++) { |
| 2647 VisitForStackValue(args->at(i)); | 2688 VisitForStackValue(args->at(i)); |
| 2648 } | 2689 } |
| 2649 } | 2690 } |
| 2691 |
| 2650 // Record source position for debugger. | 2692 // Record source position for debugger. |
| 2651 SetSourcePosition(expr->position()); | 2693 SetSourcePosition(expr->position()); |
| 2652 // Call the IC initialization code. | 2694 CallFunctionStub stub(arg_count, CALL_AS_METHOD); |
| 2653 Handle<Code> ic = | 2695 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2654 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2696 __ CallStub(&stub); |
| 2655 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2697 |
| 2656 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); | |
| 2657 RecordJSReturnSite(expr); | 2698 RecordJSReturnSite(expr); |
| 2658 // Restore context register. | 2699 // Restore context register. |
| 2659 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2700 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2660 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2701 |
| 2702 context()->DropAndPlug(1, r0); |
| 2661 } | 2703 } |
| 2662 | 2704 |
| 2663 | 2705 |
| 2664 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2706 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 2665 // Code common for calls using the call stub. | 2707 // Code common for calls using the call stub. |
| 2666 ZoneList<Expression*>* args = expr->arguments(); | 2708 ZoneList<Expression*>* args = expr->arguments(); |
| 2667 int arg_count = args->length(); | 2709 int arg_count = args->length(); |
| 2668 { PreservePositionScope scope(masm()->positions_recorder()); | 2710 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2669 for (int i = 0; i < arg_count; i++) { | 2711 for (int i = 0; i < arg_count; i++) { |
| 2670 VisitForStackValue(args->at(i)); | 2712 VisitForStackValue(args->at(i)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2758 // Record source position for debugger. | 2800 // Record source position for debugger. |
| 2759 SetSourcePosition(expr->position()); | 2801 SetSourcePosition(expr->position()); |
| 2760 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); | 2802 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 2761 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2803 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2762 __ CallStub(&stub); | 2804 __ CallStub(&stub); |
| 2763 RecordJSReturnSite(expr); | 2805 RecordJSReturnSite(expr); |
| 2764 // Restore context register. | 2806 // Restore context register. |
| 2765 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2807 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2766 context()->DropAndPlug(1, r0); | 2808 context()->DropAndPlug(1, r0); |
| 2767 } else if (call_type == Call::GLOBAL_CALL) { | 2809 } else if (call_type == Call::GLOBAL_CALL) { |
| 2768 // Push global object as receiver for the call IC. | 2810 EmitCallWithIC(expr); |
| 2769 __ ldr(r0, GlobalObjectOperand()); | 2811 |
| 2770 __ push(r0); | |
| 2771 VariableProxy* proxy = callee->AsVariableProxy(); | |
| 2772 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); | |
| 2773 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2812 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
| 2774 // Call to a lookup slot (dynamically introduced variable). | 2813 // Call to a lookup slot (dynamically introduced variable). |
| 2775 VariableProxy* proxy = callee->AsVariableProxy(); | 2814 VariableProxy* proxy = callee->AsVariableProxy(); |
| 2776 Label slow, done; | 2815 Label slow, done; |
| 2777 | 2816 |
| 2778 { PreservePositionScope scope(masm()->positions_recorder()); | 2817 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2779 // Generate code for loading from variables potentially shadowed | 2818 // Generate code for loading from variables potentially shadowed |
| 2780 // by eval-introduced variables. | 2819 // by eval-introduced variables. |
| 2781 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2820 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2782 } | 2821 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2808 | 2847 |
| 2809 // The receiver is either the global receiver or an object found | 2848 // The receiver is either the global receiver or an object found |
| 2810 // by LoadContextSlot. | 2849 // by LoadContextSlot. |
| 2811 EmitCallWithStub(expr); | 2850 EmitCallWithStub(expr); |
| 2812 } else if (call_type == Call::PROPERTY_CALL) { | 2851 } else if (call_type == Call::PROPERTY_CALL) { |
| 2813 Property* property = callee->AsProperty(); | 2852 Property* property = callee->AsProperty(); |
| 2814 { PreservePositionScope scope(masm()->positions_recorder()); | 2853 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2815 VisitForStackValue(property->obj()); | 2854 VisitForStackValue(property->obj()); |
| 2816 } | 2855 } |
| 2817 if (property->key()->IsPropertyName()) { | 2856 if (property->key()->IsPropertyName()) { |
| 2818 EmitCallWithIC(expr, | 2857 EmitCallWithIC(expr); |
| 2819 property->key()->AsLiteral()->value(), | |
| 2820 NOT_CONTEXTUAL); | |
| 2821 } else { | 2858 } else { |
| 2822 EmitKeyedCallWithIC(expr, property->key()); | 2859 EmitKeyedCallWithIC(expr, property->key()); |
| 2823 } | 2860 } |
| 2824 } else { | 2861 } else { |
| 2825 ASSERT(call_type == Call::OTHER_CALL); | 2862 ASSERT(call_type == Call::OTHER_CALL); |
| 2826 // Call to an arbitrary expression not handled specially above. | 2863 // Call to an arbitrary expression not handled specially above. |
| 2827 { PreservePositionScope scope(masm()->positions_recorder()); | 2864 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2828 VisitForStackValue(callee); | 2865 VisitForStackValue(callee); |
| 2829 } | 2866 } |
| 2830 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 2867 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| (...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4086 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4123 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 4087 Handle<String> name = expr->name(); | 4124 Handle<String> name = expr->name(); |
| 4088 if (name->length() > 0 && name->Get(0) == '_') { | 4125 if (name->length() > 0 && name->Get(0) == '_') { |
| 4089 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 4126 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
| 4090 EmitInlineRuntimeCall(expr); | 4127 EmitInlineRuntimeCall(expr); |
| 4091 return; | 4128 return; |
| 4092 } | 4129 } |
| 4093 | 4130 |
| 4094 Comment cmnt(masm_, "[ CallRuntime"); | 4131 Comment cmnt(masm_, "[ CallRuntime"); |
| 4095 ZoneList<Expression*>* args = expr->arguments(); | 4132 ZoneList<Expression*>* args = expr->arguments(); |
| 4133 int arg_count = args->length(); |
| 4096 | 4134 |
| 4097 if (expr->is_jsruntime()) { | 4135 if (expr->is_jsruntime()) { |
| 4098 // Prepare for calling JS runtime function. | 4136 // Push the builtins object as the receiver. |
| 4099 __ ldr(r0, GlobalObjectOperand()); | 4137 __ ldr(r0, GlobalObjectOperand()); |
| 4100 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 4138 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
| 4101 __ push(r0); | 4139 __ push(r0); |
| 4102 } | |
| 4103 | 4140 |
| 4104 // Push the arguments ("left-to-right"). | 4141 // Load the function from the receiver. |
| 4105 int arg_count = args->length(); | 4142 __ mov(r2, Operand(expr->name())); |
| 4106 for (int i = 0; i < arg_count; i++) { | 4143 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
| 4107 VisitForStackValue(args->at(i)); | |
| 4108 } | |
| 4109 | 4144 |
| 4110 if (expr->is_jsruntime()) { | 4145 // Push the target function under the receiver. |
| 4111 // Call the JS runtime function. | 4146 __ ldr(ip, MemOperand(sp, 0)); |
| 4112 __ mov(r2, Operand(expr->name())); | 4147 __ push(ip); |
| 4113 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 4148 __ str(r0, MemOperand(sp, kPointerSize)); |
| 4114 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 4149 |
| 4150 // Push the arguments ("left-to-right"). |
| 4151 int arg_count = args->length(); |
| 4152 { PreservePositionScope scope(masm()->positions_recorder()); |
| 4153 for (int i = 0; i < arg_count; i++) { |
| 4154 VisitForStackValue(args->at(i)); |
| 4155 } |
| 4156 } |
| 4157 // Record source position of the IC call. |
| 4158 SetSourcePosition(expr->position()); |
| 4159 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 4160 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 4161 __ CallStub(&stub); |
| 4162 |
| 4115 // Restore context register. | 4163 // Restore context register. |
| 4116 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4164 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4165 |
| 4166 context()->DropAndPlug(1, r0); |
| 4117 } else { | 4167 } else { |
| 4168 // Push the arguments ("left-to-right"). |
| 4169 { PreservePositionScope scope(masm()->positions_recorder()); |
| 4170 for (int i = 0; i < arg_count; i++) { |
| 4171 VisitForStackValue(args->at(i)); |
| 4172 } |
| 4173 } |
| 4174 |
| 4118 // Call the C runtime function. | 4175 // Call the C runtime function. |
| 4119 __ CallRuntime(expr->function(), arg_count); | 4176 __ CallRuntime(expr->function(), arg_count); |
| 4177 context()->Plug(r0); |
| 4120 } | 4178 } |
| 4121 context()->Plug(r0); | |
| 4122 } | 4179 } |
| 4123 | 4180 |
| 4124 | 4181 |
| 4125 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4182 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4126 switch (expr->op()) { | 4183 switch (expr->op()) { |
| 4127 case Token::DELETE: { | 4184 case Token::DELETE: { |
| 4128 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4185 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4129 Property* property = expr->expression()->AsProperty(); | 4186 Property* property = expr->expression()->AsProperty(); |
| 4130 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4187 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4131 | 4188 |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4866 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4923 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4867 reinterpret_cast<uint32_t>( | 4924 reinterpret_cast<uint32_t>( |
| 4868 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4925 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4869 return OSR_AFTER_STACK_CHECK; | 4926 return OSR_AFTER_STACK_CHECK; |
| 4870 } | 4927 } |
| 4871 | 4928 |
| 4872 | 4929 |
| 4873 } } // namespace v8::internal | 4930 } } // namespace v8::internal |
| 4874 | 4931 |
| 4875 #endif // V8_TARGET_ARCH_ARM | 4932 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |