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 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3807 __ bind(¬_found); | 3844 __ bind(¬_found); |
3808 // Call runtime to perform the lookup. | 3845 // Call runtime to perform the lookup. |
3809 __ Push(cache, key); | 3846 __ Push(cache, key); |
3810 __ CallRuntime(Runtime::kGetFromCache, 2); | 3847 __ CallRuntime(Runtime::kGetFromCache, 2); |
3811 | 3848 |
3812 __ bind(&done); | 3849 __ bind(&done); |
3813 context()->Plug(r0); | 3850 context()->Plug(r0); |
3814 } | 3851 } |
3815 | 3852 |
3816 | 3853 |
3817 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { | |
3818 ZoneList<Expression*>* args = expr->arguments(); | |
3819 ASSERT_EQ(2, args->length()); | |
3820 | |
3821 Register right = r0; | |
3822 Register left = r1; | |
3823 Register tmp = r2; | |
3824 Register tmp2 = r3; | |
3825 | |
3826 VisitForStackValue(args->at(0)); | |
3827 VisitForAccumulatorValue(args->at(1)); | |
3828 __ pop(left); | |
3829 | |
3830 Label done, fail, ok; | |
3831 __ cmp(left, Operand(right)); | |
3832 __ b(eq, &ok); | |
3833 // Fail if either is a non-HeapObject. | |
3834 __ and_(tmp, left, Operand(right)); | |
3835 __ JumpIfSmi(tmp, &fail); | |
3836 __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset)); | |
3837 __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset)); | |
3838 __ cmp(tmp2, Operand(JS_REGEXP_TYPE)); | |
3839 __ b(ne, &fail); | |
3840 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); | |
3841 __ cmp(tmp, Operand(tmp2)); | |
3842 __ b(ne, &fail); | |
3843 __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset)); | |
3844 __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset)); | |
3845 __ cmp(tmp, tmp2); | |
3846 __ b(eq, &ok); | |
3847 __ bind(&fail); | |
3848 __ LoadRoot(r0, Heap::kFalseValueRootIndex); | |
3849 __ jmp(&done); | |
3850 __ bind(&ok); | |
3851 __ LoadRoot(r0, Heap::kTrueValueRootIndex); | |
3852 __ bind(&done); | |
3853 | |
3854 context()->Plug(r0); | |
3855 } | |
3856 | |
3857 | |
3858 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3854 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3859 ZoneList<Expression*>* args = expr->arguments(); | 3855 ZoneList<Expression*>* args = expr->arguments(); |
3860 VisitForAccumulatorValue(args->at(0)); | 3856 VisitForAccumulatorValue(args->at(0)); |
3861 | 3857 |
3862 Label materialize_true, materialize_false; | 3858 Label materialize_true, materialize_false; |
3863 Label* if_true = NULL; | 3859 Label* if_true = NULL; |
3864 Label* if_false = NULL; | 3860 Label* if_false = NULL; |
3865 Label* fall_through = NULL; | 3861 Label* fall_through = NULL; |
3866 context()->PrepareTest(&materialize_true, &materialize_false, | 3862 context()->PrepareTest(&materialize_true, &materialize_false, |
3867 &if_true, &if_false, &fall_through); | 3863 &if_true, &if_false, &fall_through); |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4127 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4123 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
4128 Handle<String> name = expr->name(); | 4124 Handle<String> name = expr->name(); |
4129 if (name->length() > 0 && name->Get(0) == '_') { | 4125 if (name->length() > 0 && name->Get(0) == '_') { |
4130 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 4126 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
4131 EmitInlineRuntimeCall(expr); | 4127 EmitInlineRuntimeCall(expr); |
4132 return; | 4128 return; |
4133 } | 4129 } |
4134 | 4130 |
4135 Comment cmnt(masm_, "[ CallRuntime"); | 4131 Comment cmnt(masm_, "[ CallRuntime"); |
4136 ZoneList<Expression*>* args = expr->arguments(); | 4132 ZoneList<Expression*>* args = expr->arguments(); |
| 4133 int arg_count = args->length(); |
4137 | 4134 |
4138 if (expr->is_jsruntime()) { | 4135 if (expr->is_jsruntime()) { |
4139 // Prepare for calling JS runtime function. | 4136 // Push the builtins object as the receiver. |
4140 __ ldr(r0, GlobalObjectOperand()); | 4137 __ ldr(r0, GlobalObjectOperand()); |
4141 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 4138 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
4142 __ push(r0); | 4139 __ push(r0); |
4143 } | |
4144 | 4140 |
4145 // Push the arguments ("left-to-right"). | 4141 // Load the function from the receiver. |
4146 int arg_count = args->length(); | 4142 __ mov(r2, Operand(expr->name())); |
4147 for (int i = 0; i < arg_count; i++) { | 4143 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
4148 VisitForStackValue(args->at(i)); | |
4149 } | |
4150 | 4144 |
4151 if (expr->is_jsruntime()) { | 4145 // Push the target function under the receiver. |
4152 // Call the JS runtime function. | 4146 __ ldr(ip, MemOperand(sp, 0)); |
4153 __ mov(r2, Operand(expr->name())); | 4147 __ push(ip); |
4154 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 4148 __ str(r0, MemOperand(sp, kPointerSize)); |
4155 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 4149 |
| 4150 // Push the arguments ("left-to-right"). |
| 4151 int arg_count = args->length(); |
| 4152 for (int i = 0; i < arg_count; i++) { |
| 4153 VisitForStackValue(args->at(i)); |
| 4154 } |
| 4155 |
| 4156 // Record source position of the IC call. |
| 4157 SetSourcePosition(expr->position()); |
| 4158 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 4159 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 4160 __ CallStub(&stub); |
| 4161 |
4156 // Restore context register. | 4162 // Restore context register. |
4157 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4163 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4164 |
| 4165 context()->DropAndPlug(1, r0); |
4158 } else { | 4166 } else { |
| 4167 // Push the arguments ("left-to-right"). |
| 4168 for (int i = 0; i < arg_count; i++) { |
| 4169 VisitForStackValue(args->at(i)); |
| 4170 } |
| 4171 |
4159 // Call the C runtime function. | 4172 // Call the C runtime function. |
4160 __ CallRuntime(expr->function(), arg_count); | 4173 __ CallRuntime(expr->function(), arg_count); |
| 4174 context()->Plug(r0); |
4161 } | 4175 } |
4162 context()->Plug(r0); | |
4163 } | 4176 } |
4164 | 4177 |
4165 | 4178 |
4166 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4179 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
4167 switch (expr->op()) { | 4180 switch (expr->op()) { |
4168 case Token::DELETE: { | 4181 case Token::DELETE: { |
4169 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4182 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4170 Property* property = expr->expression()->AsProperty(); | 4183 Property* property = expr->expression()->AsProperty(); |
4171 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4184 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4172 | 4185 |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4907 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4920 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
4908 reinterpret_cast<uint32_t>( | 4921 reinterpret_cast<uint32_t>( |
4909 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4922 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4910 return OSR_AFTER_STACK_CHECK; | 4923 return OSR_AFTER_STACK_CHECK; |
4911 } | 4924 } |
4912 | 4925 |
4913 | 4926 |
4914 } } // namespace v8::internal | 4927 } } // namespace v8::internal |
4915 | 4928 |
4916 #endif // V8_TARGET_ARCH_ARM | 4929 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |