| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 | 135 |
| 136 Scope* CodeGenerator::scope() { return info_->function()->scope(); } | 136 Scope* CodeGenerator::scope() { return info_->function()->scope(); } |
| 137 | 137 |
| 138 | 138 |
| 139 // Calling conventions: | 139 // Calling conventions: |
| 140 // fp: caller's frame pointer | 140 // fp: caller's frame pointer |
| 141 // sp: stack pointer | 141 // sp: stack pointer |
| 142 // r1: called JS function | 142 // r1: called JS function |
| 143 // cp: callee's context | 143 // cp: callee's context |
| 144 | 144 |
| 145 void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { | 145 void CodeGenerator::Generate(CompilationInfo* info) { |
| 146 // Record the position for debugging purposes. | 146 // Record the position for debugging purposes. |
| 147 CodeForFunctionPosition(info->function()); | 147 CodeForFunctionPosition(info->function()); |
| 148 | 148 |
| 149 // Initialize state. | 149 // Initialize state. |
| 150 info_ = info; | 150 info_ = info; |
| 151 ASSERT(allocator_ == NULL); | 151 ASSERT(allocator_ == NULL); |
| 152 RegisterAllocator register_allocator(this); | 152 RegisterAllocator register_allocator(this); |
| 153 allocator_ = ®ister_allocator; | 153 allocator_ = ®ister_allocator; |
| 154 ASSERT(frame_ == NULL); | 154 ASSERT(frame_ == NULL); |
| 155 frame_ = new VirtualFrame(); | 155 frame_ = new VirtualFrame(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 167 allocator_->Initialize(); | 167 allocator_->Initialize(); |
| 168 | 168 |
| 169 #ifdef DEBUG | 169 #ifdef DEBUG |
| 170 if (strlen(FLAG_stop_at) > 0 && | 170 if (strlen(FLAG_stop_at) > 0 && |
| 171 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 171 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
| 172 frame_->SpillAll(); | 172 frame_->SpillAll(); |
| 173 __ stop("stop-at"); | 173 __ stop("stop-at"); |
| 174 } | 174 } |
| 175 #endif | 175 #endif |
| 176 | 176 |
| 177 if (mode == PRIMARY) { | 177 if (info->mode() == CompilationInfo::PRIMARY) { |
| 178 frame_->Enter(); | 178 frame_->Enter(); |
| 179 // tos: code slot | 179 // tos: code slot |
| 180 | 180 |
| 181 // Allocate space for locals and initialize them. This also checks | 181 // Allocate space for locals and initialize them. This also checks |
| 182 // for stack overflow. | 182 // for stack overflow. |
| 183 frame_->AllocateStackSlots(); | 183 frame_->AllocateStackSlots(); |
| 184 | 184 |
| 185 VirtualFrame::SpilledScope spilled_scope; | 185 VirtualFrame::SpilledScope spilled_scope; |
| 186 int heap_slots = scope()->num_heap_slots(); | 186 int heap_slots = scope()->num_heap_slots(); |
| 187 if (heap_slots > 0) { | 187 if (heap_slots > 0) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 frame_->EmitPush(ip); | 270 frame_->EmitPush(ip); |
| 271 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); | 271 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); |
| 272 } | 272 } |
| 273 } else { | 273 } else { |
| 274 // When used as the secondary compiler for splitting, r1, cp, | 274 // When used as the secondary compiler for splitting, r1, cp, |
| 275 // fp, and lr have been pushed on the stack. Adjust the virtual | 275 // fp, and lr have been pushed on the stack. Adjust the virtual |
| 276 // frame to match this state. | 276 // frame to match this state. |
| 277 frame_->Adjust(4); | 277 frame_->Adjust(4); |
| 278 allocator_->Unuse(r1); | 278 allocator_->Unuse(r1); |
| 279 allocator_->Unuse(lr); | 279 allocator_->Unuse(lr); |
| 280 |
| 281 // Bind all the bailout labels to the beginning of the function. |
| 282 List<CompilationInfo::Bailout*>* bailouts = info->bailouts(); |
| 283 for (int i = 0; i < bailouts->length(); i++) { |
| 284 __ bind(bailouts->at(i)->label()); |
| 285 } |
| 280 } | 286 } |
| 281 | 287 |
| 282 // Initialize the function return target after the locals are set | 288 // Initialize the function return target after the locals are set |
| 283 // up, because it needs the expected frame height from the frame. | 289 // up, because it needs the expected frame height from the frame. |
| 284 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 290 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
| 285 function_return_is_shadowed_ = false; | 291 function_return_is_shadowed_ = false; |
| 286 | 292 |
| 287 // Generate code to 'execute' declarations and initialize functions | 293 // Generate code to 'execute' declarations and initialize functions |
| 288 // (source elements). In case of an illegal redeclaration we need to | 294 // (source elements). In case of an illegal redeclaration we need to |
| 289 // handle that instead of processing the declarations. | 295 // handle that instead of processing the declarations. |
| (...skipping 1996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 | 2292 |
| 2287 | 2293 |
| 2288 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2294 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
| 2289 #ifdef DEBUG | 2295 #ifdef DEBUG |
| 2290 int original_height = frame_->height(); | 2296 int original_height = frame_->height(); |
| 2291 #endif | 2297 #endif |
| 2292 VirtualFrame::SpilledScope spilled_scope; | 2298 VirtualFrame::SpilledScope spilled_scope; |
| 2293 Comment cmnt(masm_, "[ DebuggerStatament"); | 2299 Comment cmnt(masm_, "[ DebuggerStatament"); |
| 2294 CodeForStatementPosition(node); | 2300 CodeForStatementPosition(node); |
| 2295 #ifdef ENABLE_DEBUGGER_SUPPORT | 2301 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 2296 DebuggerStatementStub ces; | 2302 frame_->DebugBreak(); |
| 2297 frame_->CallStub(&ces, 0); | |
| 2298 #endif | 2303 #endif |
| 2299 // Ignore the return value. | 2304 // Ignore the return value. |
| 2300 ASSERT(frame_->height() == original_height); | 2305 ASSERT(frame_->height() == original_height); |
| 2301 } | 2306 } |
| 2302 | 2307 |
| 2303 | 2308 |
| 2304 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2309 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
| 2305 VirtualFrame::SpilledScope spilled_scope; | 2310 VirtualFrame::SpilledScope spilled_scope; |
| 2306 ASSERT(boilerplate->IsBoilerplate()); | 2311 ASSERT(boilerplate->IsBoilerplate()); |
| 2307 | 2312 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2712 __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); | 2717 __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); |
| 2713 // Constant properties. | 2718 // Constant properties. |
| 2714 __ mov(r0, Operand(node->constant_properties())); | 2719 __ mov(r0, Operand(node->constant_properties())); |
| 2715 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); | 2720 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); |
| 2716 if (node->depth() > 1) { | 2721 if (node->depth() > 1) { |
| 2717 frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); | 2722 frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); |
| 2718 } else { | 2723 } else { |
| 2719 frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 2724 frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
| 2720 } | 2725 } |
| 2721 frame_->EmitPush(r0); // save the result | 2726 frame_->EmitPush(r0); // save the result |
| 2722 // r0: created object literal | |
| 2723 | |
| 2724 for (int i = 0; i < node->properties()->length(); i++) { | 2727 for (int i = 0; i < node->properties()->length(); i++) { |
| 2728 // At the start of each iteration, the top of stack contains |
| 2729 // the newly created object literal. |
| 2725 ObjectLiteral::Property* property = node->properties()->at(i); | 2730 ObjectLiteral::Property* property = node->properties()->at(i); |
| 2726 Literal* key = property->key(); | 2731 Literal* key = property->key(); |
| 2727 Expression* value = property->value(); | 2732 Expression* value = property->value(); |
| 2728 switch (property->kind()) { | 2733 switch (property->kind()) { |
| 2729 case ObjectLiteral::Property::CONSTANT: | 2734 case ObjectLiteral::Property::CONSTANT: |
| 2730 break; | 2735 break; |
| 2731 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2736 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2732 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 2737 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
| 2733 // else fall through | 2738 // else fall through |
| 2734 case ObjectLiteral::Property::COMPUTED: // fall through | 2739 case ObjectLiteral::Property::COMPUTED: |
| 2740 if (key->handle()->IsSymbol()) { |
| 2741 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 2742 LoadAndSpill(value); |
| 2743 frame_->EmitPop(r0); |
| 2744 __ mov(r2, Operand(key->handle())); |
| 2745 __ ldr(r1, frame_->Top()); // Load the receiver. |
| 2746 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 2747 break; |
| 2748 } |
| 2749 // else fall through |
| 2735 case ObjectLiteral::Property::PROTOTYPE: { | 2750 case ObjectLiteral::Property::PROTOTYPE: { |
| 2751 __ ldr(r0, frame_->Top()); |
| 2736 frame_->EmitPush(r0); // dup the result | 2752 frame_->EmitPush(r0); // dup the result |
| 2737 LoadAndSpill(key); | 2753 LoadAndSpill(key); |
| 2738 LoadAndSpill(value); | 2754 LoadAndSpill(value); |
| 2739 frame_->CallRuntime(Runtime::kSetProperty, 3); | 2755 frame_->CallRuntime(Runtime::kSetProperty, 3); |
| 2740 // restore r0 | |
| 2741 __ ldr(r0, frame_->Top()); | |
| 2742 break; | 2756 break; |
| 2743 } | 2757 } |
| 2744 case ObjectLiteral::Property::SETTER: { | 2758 case ObjectLiteral::Property::SETTER: { |
| 2759 __ ldr(r0, frame_->Top()); |
| 2745 frame_->EmitPush(r0); | 2760 frame_->EmitPush(r0); |
| 2746 LoadAndSpill(key); | 2761 LoadAndSpill(key); |
| 2747 __ mov(r0, Operand(Smi::FromInt(1))); | 2762 __ mov(r0, Operand(Smi::FromInt(1))); |
| 2748 frame_->EmitPush(r0); | 2763 frame_->EmitPush(r0); |
| 2749 LoadAndSpill(value); | 2764 LoadAndSpill(value); |
| 2750 frame_->CallRuntime(Runtime::kDefineAccessor, 4); | 2765 frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
| 2751 __ ldr(r0, frame_->Top()); | |
| 2752 break; | 2766 break; |
| 2753 } | 2767 } |
| 2754 case ObjectLiteral::Property::GETTER: { | 2768 case ObjectLiteral::Property::GETTER: { |
| 2769 __ ldr(r0, frame_->Top()); |
| 2755 frame_->EmitPush(r0); | 2770 frame_->EmitPush(r0); |
| 2756 LoadAndSpill(key); | 2771 LoadAndSpill(key); |
| 2757 __ mov(r0, Operand(Smi::FromInt(0))); | 2772 __ mov(r0, Operand(Smi::FromInt(0))); |
| 2758 frame_->EmitPush(r0); | 2773 frame_->EmitPush(r0); |
| 2759 LoadAndSpill(value); | 2774 LoadAndSpill(value); |
| 2760 frame_->CallRuntime(Runtime::kDefineAccessor, 4); | 2775 frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
| 2761 __ ldr(r0, frame_->Top()); | |
| 2762 break; | 2776 break; |
| 2763 } | 2777 } |
| 2764 } | 2778 } |
| 2765 } | 2779 } |
| 2766 ASSERT(frame_->height() == original_height + 1); | 2780 ASSERT(frame_->height() == original_height + 1); |
| 2767 } | 2781 } |
| 2768 | 2782 |
| 2769 | 2783 |
| 2770 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2784 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
| 2771 #ifdef DEBUG | 2785 #ifdef DEBUG |
| 2772 int original_height = frame_->height(); | 2786 int original_height = frame_->height(); |
| 2773 #endif | 2787 #endif |
| 2774 VirtualFrame::SpilledScope spilled_scope; | 2788 VirtualFrame::SpilledScope spilled_scope; |
| 2775 Comment cmnt(masm_, "[ ArrayLiteral"); | 2789 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 2776 | 2790 |
| 2777 // Load the function of this activation. | 2791 // Load the function of this activation. |
| 2778 __ ldr(r2, frame_->Function()); | 2792 __ ldr(r2, frame_->Function()); |
| 2779 // Literals array. | 2793 // Load the literals array of the function. |
| 2780 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 2794 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
| 2781 // Literal index. | |
| 2782 __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); | 2795 __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); |
| 2783 // Constant elements. | |
| 2784 __ mov(r0, Operand(node->constant_elements())); | 2796 __ mov(r0, Operand(node->constant_elements())); |
| 2785 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); | 2797 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); |
| 2798 int length = node->values()->length(); |
| 2786 if (node->depth() > 1) { | 2799 if (node->depth() > 1) { |
| 2787 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); | 2800 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 2801 } else if (length > FastCloneShallowArrayStub::kMaximumLength) { |
| 2802 frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
| 2788 } else { | 2803 } else { |
| 2789 frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 2804 FastCloneShallowArrayStub stub(length); |
| 2805 frame_->CallStub(&stub, 3); |
| 2790 } | 2806 } |
| 2791 frame_->EmitPush(r0); // save the result | 2807 frame_->EmitPush(r0); // save the result |
| 2792 // r0: created object literal | 2808 // r0: created object literal |
| 2793 | 2809 |
| 2794 // Generate code to set the elements in the array that are not | 2810 // Generate code to set the elements in the array that are not |
| 2795 // literals. | 2811 // literals. |
| 2796 for (int i = 0; i < node->values()->length(); i++) { | 2812 for (int i = 0; i < node->values()->length(); i++) { |
| 2797 Expression* value = node->values()->at(i); | 2813 Expression* value = node->values()->at(i); |
| 2798 | 2814 |
| 2799 // If value is a literal the property value is already set in the | 2815 // If value is a literal the property value is already set in the |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3006 | 3022 |
| 3007 __ ldr(cp, frame_->Context()); | 3023 __ ldr(cp, frame_->Context()); |
| 3008 // Remove the function from the stack. | 3024 // Remove the function from the stack. |
| 3009 frame_->Drop(); | 3025 frame_->Drop(); |
| 3010 frame_->EmitPush(r0); | 3026 frame_->EmitPush(r0); |
| 3011 | 3027 |
| 3012 } else if (var != NULL && !var->is_this() && var->is_global()) { | 3028 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 3013 // ---------------------------------- | 3029 // ---------------------------------- |
| 3014 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 3030 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
| 3015 // ---------------------------------- | 3031 // ---------------------------------- |
| 3016 | |
| 3017 // Push the name of the function and the receiver onto the stack. | |
| 3018 __ mov(r0, Operand(var->name())); | |
| 3019 frame_->EmitPush(r0); | |
| 3020 | |
| 3021 // Pass the global object as the receiver and let the IC stub | 3032 // Pass the global object as the receiver and let the IC stub |
| 3022 // patch the stack to use the global proxy as 'this' in the | 3033 // patch the stack to use the global proxy as 'this' in the |
| 3023 // invoked function. | 3034 // invoked function. |
| 3024 LoadGlobal(); | 3035 LoadGlobal(); |
| 3025 | 3036 |
| 3026 // Load the arguments. | 3037 // Load the arguments. |
| 3027 int arg_count = args->length(); | 3038 int arg_count = args->length(); |
| 3028 for (int i = 0; i < arg_count; i++) { | 3039 for (int i = 0; i < arg_count; i++) { |
| 3029 LoadAndSpill(args->at(i)); | 3040 LoadAndSpill(args->at(i)); |
| 3030 } | 3041 } |
| 3031 | 3042 |
| 3032 // Setup the receiver register and call the IC initialization code. | 3043 // Setup the name register and call the IC initialization code. |
| 3044 __ mov(r2, Operand(var->name())); |
| 3033 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3045 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 3034 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3046 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
| 3035 CodeForSourcePosition(node->position()); | 3047 CodeForSourcePosition(node->position()); |
| 3036 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 3048 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
| 3037 arg_count + 1); | 3049 arg_count + 1); |
| 3038 __ ldr(cp, frame_->Context()); | 3050 __ ldr(cp, frame_->Context()); |
| 3039 // Remove the function from the stack. | |
| 3040 frame_->Drop(); | |
| 3041 frame_->EmitPush(r0); | 3051 frame_->EmitPush(r0); |
| 3042 | 3052 |
| 3043 } else if (var != NULL && var->slot() != NULL && | 3053 } else if (var != NULL && var->slot() != NULL && |
| 3044 var->slot()->type() == Slot::LOOKUP) { | 3054 var->slot()->type() == Slot::LOOKUP) { |
| 3045 // ---------------------------------- | 3055 // ---------------------------------- |
| 3046 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 3056 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
| 3047 // ---------------------------------- | 3057 // ---------------------------------- |
| 3048 | 3058 |
| 3049 // Load the function | 3059 // Load the function |
| 3050 frame_->EmitPush(cp); | 3060 frame_->EmitPush(cp); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3063 | 3073 |
| 3064 } else if (property != NULL) { | 3074 } else if (property != NULL) { |
| 3065 // Check if the key is a literal string. | 3075 // Check if the key is a literal string. |
| 3066 Literal* literal = property->key()->AsLiteral(); | 3076 Literal* literal = property->key()->AsLiteral(); |
| 3067 | 3077 |
| 3068 if (literal != NULL && literal->handle()->IsSymbol()) { | 3078 if (literal != NULL && literal->handle()->IsSymbol()) { |
| 3069 // ------------------------------------------------------------------ | 3079 // ------------------------------------------------------------------ |
| 3070 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 3080 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
| 3071 // ------------------------------------------------------------------ | 3081 // ------------------------------------------------------------------ |
| 3072 | 3082 |
| 3073 // Push the name of the function and the receiver onto the stack. | 3083 LoadAndSpill(property->obj()); // Receiver. |
| 3074 __ mov(r0, Operand(literal->handle())); | |
| 3075 frame_->EmitPush(r0); | |
| 3076 LoadAndSpill(property->obj()); | |
| 3077 | |
| 3078 // Load the arguments. | 3084 // Load the arguments. |
| 3079 int arg_count = args->length(); | 3085 int arg_count = args->length(); |
| 3080 for (int i = 0; i < arg_count; i++) { | 3086 for (int i = 0; i < arg_count; i++) { |
| 3081 LoadAndSpill(args->at(i)); | 3087 LoadAndSpill(args->at(i)); |
| 3082 } | 3088 } |
| 3083 | 3089 |
| 3084 // Set the receiver register and call the IC initialization code. | 3090 // Set the name register and call the IC initialization code. |
| 3091 __ mov(r2, Operand(literal->handle())); |
| 3085 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3092 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 3086 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3093 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
| 3087 CodeForSourcePosition(node->position()); | 3094 CodeForSourcePosition(node->position()); |
| 3088 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3095 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
| 3089 __ ldr(cp, frame_->Context()); | 3096 __ ldr(cp, frame_->Context()); |
| 3090 | 3097 frame_->EmitPush(r0); |
| 3091 // Remove the function from the stack. | |
| 3092 frame_->Drop(); | |
| 3093 | |
| 3094 frame_->EmitPush(r0); // push after get rid of function from the stack | |
| 3095 | 3098 |
| 3096 } else { | 3099 } else { |
| 3097 // ------------------------------------------- | 3100 // ------------------------------------------- |
| 3098 // JavaScript example: 'array[index](1, 2, 3)' | 3101 // JavaScript example: 'array[index](1, 2, 3)' |
| 3099 // ------------------------------------------- | 3102 // ------------------------------------------- |
| 3100 | 3103 |
| 3101 LoadAndSpill(property->obj()); | 3104 LoadAndSpill(property->obj()); |
| 3102 LoadAndSpill(property->key()); | 3105 LoadAndSpill(property->key()); |
| 3103 EmitKeyedLoad(false); | 3106 EmitKeyedLoad(false); |
| 3104 frame_->Drop(); // key | 3107 frame_->Drop(); // key |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3416 __ and_(r1, r0, Operand(kSmiTagMask)); | 3419 __ and_(r1, r0, Operand(kSmiTagMask)); |
| 3417 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); | 3420 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); |
| 3418 answer.Branch(ne); | 3421 answer.Branch(ne); |
| 3419 // It is a heap object - get the map. Check if the object is a JS array. | 3422 // It is a heap object - get the map. Check if the object is a JS array. |
| 3420 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 3423 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 3421 answer.Bind(); | 3424 answer.Bind(); |
| 3422 cc_reg_ = eq; | 3425 cc_reg_ = eq; |
| 3423 } | 3426 } |
| 3424 | 3427 |
| 3425 | 3428 |
| 3429 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
| 3430 VirtualFrame::SpilledScope spilled_scope; |
| 3431 ASSERT(args->length() == 1); |
| 3432 LoadAndSpill(args->at(0)); |
| 3433 JumpTarget answer; |
| 3434 // We need the CC bits to come out as not_equal in the case where the |
| 3435 // object is a smi. This can't be done with the usual test opcode so |
| 3436 // we use XOR to get the right CC bits. |
| 3437 frame_->EmitPop(r0); |
| 3438 __ and_(r1, r0, Operand(kSmiTagMask)); |
| 3439 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); |
| 3440 answer.Branch(ne); |
| 3441 // It is a heap object - get the map. Check if the object is a regexp. |
| 3442 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
| 3443 answer.Bind(); |
| 3444 cc_reg_ = eq; |
| 3445 } |
| 3446 |
| 3447 |
| 3426 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { | 3448 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { |
| 3427 // This generates a fast version of: | 3449 // This generates a fast version of: |
| 3428 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') | 3450 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') |
| 3429 VirtualFrame::SpilledScope spilled_scope; | 3451 VirtualFrame::SpilledScope spilled_scope; |
| 3430 ASSERT(args->length() == 1); | 3452 ASSERT(args->length() == 1); |
| 3431 LoadAndSpill(args->at(0)); | 3453 LoadAndSpill(args->at(0)); |
| 3432 frame_->EmitPop(r1); | 3454 frame_->EmitPop(r1); |
| 3433 __ tst(r1, Operand(kSmiTagMask)); | 3455 __ tst(r1, Operand(kSmiTagMask)); |
| 3434 false_target()->Branch(eq); | 3456 false_target()->Branch(eq); |
| 3435 | 3457 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3588 Load(args->at(0)); | 3610 Load(args->at(0)); |
| 3589 Load(args->at(1)); | 3611 Load(args->at(1)); |
| 3590 Load(args->at(2)); | 3612 Load(args->at(2)); |
| 3591 Load(args->at(3)); | 3613 Load(args->at(3)); |
| 3592 | 3614 |
| 3593 frame_->CallRuntime(Runtime::kRegExpExec, 4); | 3615 frame_->CallRuntime(Runtime::kRegExpExec, 4); |
| 3594 frame_->EmitPush(r0); | 3616 frame_->EmitPush(r0); |
| 3595 } | 3617 } |
| 3596 | 3618 |
| 3597 | 3619 |
| 3620 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
| 3621 ASSERT_EQ(args->length(), 1); |
| 3622 |
| 3623 // Load the argument on the stack and jump to the runtime. |
| 3624 Load(args->at(0)); |
| 3625 |
| 3626 frame_->CallRuntime(Runtime::kNumberToString, 1); |
| 3627 frame_->EmitPush(r0); |
| 3628 } |
| 3629 |
| 3630 |
| 3631 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 3632 ASSERT_EQ(args->length(), 1); |
| 3633 // Load the argument on the stack and jump to the runtime. |
| 3634 Load(args->at(0)); |
| 3635 frame_->CallRuntime(Runtime::kMath_sin, 1); |
| 3636 frame_->EmitPush(r0); |
| 3637 } |
| 3638 |
| 3639 |
| 3640 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 3641 ASSERT_EQ(args->length(), 1); |
| 3642 // Load the argument on the stack and jump to the runtime. |
| 3643 Load(args->at(0)); |
| 3644 frame_->CallRuntime(Runtime::kMath_cos, 1); |
| 3645 frame_->EmitPush(r0); |
| 3646 } |
| 3647 |
| 3648 |
| 3598 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 3649 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 3599 VirtualFrame::SpilledScope spilled_scope; | 3650 VirtualFrame::SpilledScope spilled_scope; |
| 3600 ASSERT(args->length() == 2); | 3651 ASSERT(args->length() == 2); |
| 3601 | 3652 |
| 3602 // Load the two objects into registers and perform the comparison. | 3653 // Load the two objects into registers and perform the comparison. |
| 3603 LoadAndSpill(args->at(0)); | 3654 LoadAndSpill(args->at(0)); |
| 3604 LoadAndSpill(args->at(1)); | 3655 LoadAndSpill(args->at(1)); |
| 3605 frame_->EmitPop(r0); | 3656 frame_->EmitPop(r0); |
| 3606 frame_->EmitPop(r1); | 3657 frame_->EmitPop(r1); |
| 3607 __ cmp(r0, Operand(r1)); | 3658 __ cmp(r0, Operand(r1)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3619 (!has_cc() && frame_->height() == original_height + 1)); | 3670 (!has_cc() && frame_->height() == original_height + 1)); |
| 3620 return; | 3671 return; |
| 3621 } | 3672 } |
| 3622 | 3673 |
| 3623 ZoneList<Expression*>* args = node->arguments(); | 3674 ZoneList<Expression*>* args = node->arguments(); |
| 3624 Comment cmnt(masm_, "[ CallRuntime"); | 3675 Comment cmnt(masm_, "[ CallRuntime"); |
| 3625 Runtime::Function* function = node->function(); | 3676 Runtime::Function* function = node->function(); |
| 3626 | 3677 |
| 3627 if (function == NULL) { | 3678 if (function == NULL) { |
| 3628 // Prepare stack for calling JS runtime function. | 3679 // Prepare stack for calling JS runtime function. |
| 3629 __ mov(r0, Operand(node->name())); | |
| 3630 frame_->EmitPush(r0); | |
| 3631 // Push the builtins object found in the current global object. | 3680 // Push the builtins object found in the current global object. |
| 3632 __ ldr(r1, GlobalObject()); | 3681 __ ldr(r1, GlobalObject()); |
| 3633 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); | 3682 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); |
| 3634 frame_->EmitPush(r0); | 3683 frame_->EmitPush(r0); |
| 3635 } | 3684 } |
| 3636 | 3685 |
| 3637 // Push the arguments ("left-to-right"). | 3686 // Push the arguments ("left-to-right"). |
| 3638 int arg_count = args->length(); | 3687 int arg_count = args->length(); |
| 3639 for (int i = 0; i < arg_count; i++) { | 3688 for (int i = 0; i < arg_count; i++) { |
| 3640 LoadAndSpill(args->at(i)); | 3689 LoadAndSpill(args->at(i)); |
| 3641 } | 3690 } |
| 3642 | 3691 |
| 3643 if (function == NULL) { | 3692 if (function == NULL) { |
| 3644 // Call the JS runtime function. | 3693 // Call the JS runtime function. |
| 3694 __ mov(r2, Operand(node->name())); |
| 3645 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3695 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 3646 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3696 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
| 3647 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3697 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
| 3648 __ ldr(cp, frame_->Context()); | 3698 __ ldr(cp, frame_->Context()); |
| 3649 frame_->Drop(); | |
| 3650 frame_->EmitPush(r0); | 3699 frame_->EmitPush(r0); |
| 3651 } else { | 3700 } else { |
| 3652 // Call the C runtime function. | 3701 // Call the C runtime function. |
| 3653 frame_->CallRuntime(function, arg_count); | 3702 frame_->CallRuntime(function, arg_count); |
| 3654 frame_->EmitPush(r0); | 3703 frame_->EmitPush(r0); |
| 3655 } | 3704 } |
| 3656 ASSERT(frame_->height() == original_height + 1); | 3705 ASSERT(frame_->height() == original_height + 1); |
| 3657 } | 3706 } |
| 3658 | 3707 |
| 3659 | 3708 |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4382 break; | 4431 break; |
| 4383 } | 4432 } |
| 4384 | 4433 |
| 4385 case NAMED: { | 4434 case NAMED: { |
| 4386 Comment cmnt(masm, "[ Store to named Property"); | 4435 Comment cmnt(masm, "[ Store to named Property"); |
| 4387 // Call the appropriate IC code. | 4436 // Call the appropriate IC code. |
| 4388 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 4437 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 4389 Handle<String> name(GetName()); | 4438 Handle<String> name(GetName()); |
| 4390 | 4439 |
| 4391 frame->EmitPop(r0); | 4440 frame->EmitPop(r0); |
| 4392 // Setup the name register. | 4441 frame->EmitPop(r1); |
| 4393 __ mov(r2, Operand(name)); | 4442 __ mov(r2, Operand(name)); |
| 4394 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4443 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 4395 frame->EmitPush(r0); | 4444 frame->EmitPush(r0); |
| 4396 cgen_->UnloadReference(this); | 4445 set_unloaded(); |
| 4397 break; | 4446 break; |
| 4398 } | 4447 } |
| 4399 | 4448 |
| 4400 case KEYED: { | 4449 case KEYED: { |
| 4401 Comment cmnt(masm, "[ Store to keyed Property"); | 4450 Comment cmnt(masm, "[ Store to keyed Property"); |
| 4402 Property* property = expression_->AsProperty(); | 4451 Property* property = expression_->AsProperty(); |
| 4403 ASSERT(property != NULL); | 4452 ASSERT(property != NULL); |
| 4404 cgen_->CodeForSourcePosition(property->position()); | 4453 cgen_->CodeForSourcePosition(property->position()); |
| 4405 | 4454 |
| 4406 // Call IC code. | 4455 // Call IC code. |
| 4407 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 4456 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 4408 // TODO(1222589): Make the IC grab the values from the stack. | |
| 4409 frame->EmitPop(r0); // value | 4457 frame->EmitPop(r0); // value |
| 4410 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4458 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 4411 frame->EmitPush(r0); | 4459 frame->EmitPush(r0); |
| 4412 cgen_->UnloadReference(this); | 4460 cgen_->UnloadReference(this); |
| 4413 break; | 4461 break; |
| 4414 } | 4462 } |
| 4415 | 4463 |
| 4416 default: | 4464 default: |
| 4417 UNREACHABLE(); | 4465 UNREACHABLE(); |
| 4418 } | 4466 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4473 | 4521 |
| 4474 // Attempt to allocate the context in new space. | 4522 // Attempt to allocate the context in new space. |
| 4475 __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize), | 4523 __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize), |
| 4476 r0, | 4524 r0, |
| 4477 r1, | 4525 r1, |
| 4478 r2, | 4526 r2, |
| 4479 &gc, | 4527 &gc, |
| 4480 TAG_OBJECT); | 4528 TAG_OBJECT); |
| 4481 | 4529 |
| 4482 // Load the function from the stack. | 4530 // Load the function from the stack. |
| 4483 __ ldr(r3, MemOperand(sp, 0 * kPointerSize)); | 4531 __ ldr(r3, MemOperand(sp, 0)); |
| 4484 | 4532 |
| 4485 // Setup the object header. | 4533 // Setup the object header. |
| 4486 __ LoadRoot(r2, Heap::kContextMapRootIndex); | 4534 __ LoadRoot(r2, Heap::kContextMapRootIndex); |
| 4487 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4535 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 4488 __ mov(r2, Operand(length)); | 4536 __ mov(r2, Operand(length)); |
| 4489 __ str(r2, FieldMemOperand(r0, Array::kLengthOffset)); | 4537 __ str(r2, FieldMemOperand(r0, Array::kLengthOffset)); |
| 4490 | 4538 |
| 4491 // Setup the fixed slots. | 4539 // Setup the fixed slots. |
| 4492 __ mov(r1, Operand(Smi::FromInt(0))); | 4540 __ mov(r1, Operand(Smi::FromInt(0))); |
| 4493 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); | 4541 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4509 __ mov(cp, r0); | 4557 __ mov(cp, r0); |
| 4510 __ pop(); | 4558 __ pop(); |
| 4511 __ Ret(); | 4559 __ Ret(); |
| 4512 | 4560 |
| 4513 // Need to collect. Call into runtime system. | 4561 // Need to collect. Call into runtime system. |
| 4514 __ bind(&gc); | 4562 __ bind(&gc); |
| 4515 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); | 4563 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); |
| 4516 } | 4564 } |
| 4517 | 4565 |
| 4518 | 4566 |
| 4567 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { |
| 4568 // Stack layout on entry: |
| 4569 // |
| 4570 // [sp]: constant elements. |
| 4571 // [sp + kPointerSize]: literal index. |
| 4572 // [sp + (2 * kPointerSize)]: literals array. |
| 4573 |
| 4574 // All sizes here are multiples of kPointerSize. |
| 4575 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; |
| 4576 int size = JSArray::kSize + elements_size; |
| 4577 |
| 4578 // Load boilerplate object into r3 and check if we need to create a |
| 4579 // boilerplate. |
| 4580 Label slow_case; |
| 4581 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); |
| 4582 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); |
| 4583 __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4584 __ ldr(r3, MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4585 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4586 __ cmp(r3, ip); |
| 4587 __ b(eq, &slow_case); |
| 4588 |
| 4589 // Allocate both the JS array and the elements array in one big |
| 4590 // allocation. This avoids multiple limit checks. |
| 4591 __ AllocateInNewSpace(size / kPointerSize, |
| 4592 r0, |
| 4593 r1, |
| 4594 r2, |
| 4595 &slow_case, |
| 4596 TAG_OBJECT); |
| 4597 |
| 4598 // Copy the JS array part. |
| 4599 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 4600 if ((i != JSArray::kElementsOffset) || (length_ == 0)) { |
| 4601 __ ldr(r1, FieldMemOperand(r3, i)); |
| 4602 __ str(r1, FieldMemOperand(r0, i)); |
| 4603 } |
| 4604 } |
| 4605 |
| 4606 if (length_ > 0) { |
| 4607 // Get hold of the elements array of the boilerplate and setup the |
| 4608 // elements pointer in the resulting object. |
| 4609 __ ldr(r3, FieldMemOperand(r3, JSArray::kElementsOffset)); |
| 4610 __ add(r2, r0, Operand(JSArray::kSize)); |
| 4611 __ str(r2, FieldMemOperand(r0, JSArray::kElementsOffset)); |
| 4612 |
| 4613 // Copy the elements array. |
| 4614 for (int i = 0; i < elements_size; i += kPointerSize) { |
| 4615 __ ldr(r1, FieldMemOperand(r3, i)); |
| 4616 __ str(r1, FieldMemOperand(r2, i)); |
| 4617 } |
| 4618 } |
| 4619 |
| 4620 // Return and remove the on-stack parameters. |
| 4621 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 4622 __ Ret(); |
| 4623 |
| 4624 __ bind(&slow_case); |
| 4625 ExternalReference runtime(Runtime::kCreateArrayLiteralShallow); |
| 4626 __ TailCallRuntime(runtime, 3, 1); |
| 4627 } |
| 4628 |
| 4629 |
| 4519 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz | 4630 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz |
| 4520 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 | 4631 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 |
| 4521 // (31 instead of 32). | 4632 // (31 instead of 32). |
| 4522 static void CountLeadingZeros( | 4633 static void CountLeadingZeros( |
| 4523 MacroAssembler* masm, | 4634 MacroAssembler* masm, |
| 4524 Register source, | 4635 Register source, |
| 4525 Register scratch, | 4636 Register scratch, |
| 4526 Register zeros) { | 4637 Register zeros) { |
| 4527 #ifdef CAN_USE_ARMV5_INSTRUCTIONS | 4638 #ifdef CAN_USE_ARMV5_INSTRUCTIONS |
| 4528 __ clz(zeros, source); // This instruction is only supported after ARM5. | 4639 __ clz(zeros, source); // This instruction is only supported after ARM5. |
| (...skipping 2048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6577 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); | 6688 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); |
| 6578 __ BranchOnSmi(r0, &slow); | 6689 __ BranchOnSmi(r0, &slow); |
| 6579 | 6690 |
| 6580 // Check that the left hand is a JS object and put map in r3. | 6691 // Check that the left hand is a JS object and put map in r3. |
| 6581 __ CompareObjectType(r0, r3, r2, FIRST_JS_OBJECT_TYPE); | 6692 __ CompareObjectType(r0, r3, r2, FIRST_JS_OBJECT_TYPE); |
| 6582 __ b(lt, &slow); | 6693 __ b(lt, &slow); |
| 6583 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); | 6694 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); |
| 6584 __ b(gt, &slow); | 6695 __ b(gt, &slow); |
| 6585 | 6696 |
| 6586 // Get the prototype of the function (r4 is result, r2 is scratch). | 6697 // Get the prototype of the function (r4 is result, r2 is scratch). |
| 6587 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); | 6698 __ ldr(r1, MemOperand(sp, 0)); |
| 6588 __ TryGetFunctionPrototype(r1, r4, r2, &slow); | 6699 __ TryGetFunctionPrototype(r1, r4, r2, &slow); |
| 6589 | 6700 |
| 6590 // Check that the function prototype is a JS object. | 6701 // Check that the function prototype is a JS object. |
| 6591 __ BranchOnSmi(r4, &slow); | 6702 __ BranchOnSmi(r4, &slow); |
| 6592 __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE); | 6703 __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE); |
| 6593 __ b(lt, &slow); | 6704 __ b(lt, &slow); |
| 6594 __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE)); | 6705 __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE)); |
| 6595 __ b(gt, &slow); | 6706 __ b(gt, &slow); |
| 6596 | 6707 |
| 6597 // Register mapping: r3 is object map and r4 is function prototype. | 6708 // Register mapping: r3 is object map and r4 is function prototype. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6692 | 6803 |
| 6693 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 6804 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 6694 // by calling the runtime system. | 6805 // by calling the runtime system. |
| 6695 __ bind(&slow); | 6806 __ bind(&slow); |
| 6696 __ push(r1); | 6807 __ push(r1); |
| 6697 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1, 1); | 6808 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1, 1); |
| 6698 } | 6809 } |
| 6699 | 6810 |
| 6700 | 6811 |
| 6701 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | 6812 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { |
| 6813 // sp[0] : number of parameters |
| 6814 // sp[4] : receiver displacement |
| 6815 // sp[8] : function |
| 6816 |
| 6702 // Check if the calling frame is an arguments adaptor frame. | 6817 // Check if the calling frame is an arguments adaptor frame. |
| 6703 Label runtime; | 6818 Label adaptor_frame, try_allocate, runtime; |
| 6704 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 6819 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 6705 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 6820 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
| 6706 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 6821 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 6707 __ b(ne, &runtime); | 6822 __ b(eq, &adaptor_frame); |
| 6823 |
| 6824 // Get the length from the frame. |
| 6825 __ ldr(r1, MemOperand(sp, 0)); |
| 6826 __ b(&try_allocate); |
| 6708 | 6827 |
| 6709 // Patch the arguments.length and the parameters pointer. | 6828 // Patch the arguments.length and the parameters pointer. |
| 6710 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 6829 __ bind(&adaptor_frame); |
| 6711 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 6830 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 6712 __ add(r3, r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 6831 __ str(r1, MemOperand(sp, 0)); |
| 6832 __ add(r3, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 6713 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | 6833 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 6714 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | 6834 __ str(r3, MemOperand(sp, 1 * kPointerSize)); |
| 6715 | 6835 |
| 6836 // Try the new space allocation. Start out with computing the size |
| 6837 // of the arguments object and the elements array (in words, not |
| 6838 // bytes because AllocateInNewSpace expects words). |
| 6839 Label add_arguments_object; |
| 6840 __ bind(&try_allocate); |
| 6841 __ cmp(r1, Operand(0)); |
| 6842 __ b(eq, &add_arguments_object); |
| 6843 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); |
| 6844 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 6845 __ bind(&add_arguments_object); |
| 6846 __ add(r1, r1, Operand(Heap::kArgumentsObjectSize / kPointerSize)); |
| 6847 |
| 6848 // Do the allocation of both objects in one go. |
| 6849 __ AllocateInNewSpace(r1, r0, r2, r3, &runtime, TAG_OBJECT); |
| 6850 |
| 6851 // Get the arguments boilerplate from the current (global) context. |
| 6852 int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX); |
| 6853 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 6854 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset)); |
| 6855 __ ldr(r4, MemOperand(r4, offset)); |
| 6856 |
| 6857 // Copy the JS object part. |
| 6858 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 6859 __ ldr(r3, FieldMemOperand(r4, i)); |
| 6860 __ str(r3, FieldMemOperand(r0, i)); |
| 6861 } |
| 6862 |
| 6863 // Setup the callee in-object property. |
| 6864 ASSERT(Heap::arguments_callee_index == 0); |
| 6865 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); |
| 6866 __ str(r3, FieldMemOperand(r0, JSObject::kHeaderSize)); |
| 6867 |
| 6868 // Get the length (smi tagged) and set that as an in-object property too. |
| 6869 ASSERT(Heap::arguments_length_index == 1); |
| 6870 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); |
| 6871 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + kPointerSize)); |
| 6872 |
| 6873 // If there are no actual arguments, we're done. |
| 6874 Label done; |
| 6875 __ cmp(r1, Operand(0)); |
| 6876 __ b(eq, &done); |
| 6877 |
| 6878 // Get the parameters pointer from the stack and untag the length. |
| 6879 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); |
| 6880 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); |
| 6881 |
| 6882 // Setup the elements pointer in the allocated arguments object and |
| 6883 // initialize the header in the elements fixed array. |
| 6884 __ add(r4, r0, Operand(Heap::kArgumentsObjectSize)); |
| 6885 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 6886 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); |
| 6887 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); |
| 6888 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 6889 |
| 6890 // Copy the fixed array slots. |
| 6891 Label loop; |
| 6892 // Setup r4 to point to the first array slot. |
| 6893 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 6894 __ bind(&loop); |
| 6895 // Pre-decrement r2 with kPointerSize on each iteration. |
| 6896 // Pre-decrement in order to skip receiver. |
| 6897 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); |
| 6898 // Post-increment r4 with kPointerSize on each iteration. |
| 6899 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); |
| 6900 __ sub(r1, r1, Operand(1)); |
| 6901 __ cmp(r1, Operand(0)); |
| 6902 __ b(ne, &loop); |
| 6903 |
| 6904 // Return and remove the on-stack parameters. |
| 6905 __ bind(&done); |
| 6906 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 6907 __ Ret(); |
| 6908 |
| 6716 // Do the runtime call to allocate the arguments object. | 6909 // Do the runtime call to allocate the arguments object. |
| 6717 __ bind(&runtime); | 6910 __ bind(&runtime); |
| 6718 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); | 6911 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); |
| 6719 } | 6912 } |
| 6720 | 6913 |
| 6721 | 6914 |
| 6722 void CallFunctionStub::Generate(MacroAssembler* masm) { | 6915 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 6723 Label slow; | 6916 Label slow; |
| 6724 | 6917 |
| 6725 // If the receiver might be a value (string, number or boolean) check for this | 6918 // If the receiver might be a value (string, number or boolean) check for this |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6759 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 6952 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 6760 __ b(ne, &slow); | 6953 __ b(ne, &slow); |
| 6761 | 6954 |
| 6762 // Fast-case: Invoke the function now. | 6955 // Fast-case: Invoke the function now. |
| 6763 // r1: pushed function | 6956 // r1: pushed function |
| 6764 ParameterCount actual(argc_); | 6957 ParameterCount actual(argc_); |
| 6765 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | 6958 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
| 6766 | 6959 |
| 6767 // Slow-case: Non-function called. | 6960 // Slow-case: Non-function called. |
| 6768 __ bind(&slow); | 6961 __ bind(&slow); |
| 6962 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 6963 // of the original receiver from the call site). |
| 6964 __ str(r1, MemOperand(sp, argc_ * kPointerSize)); |
| 6769 __ mov(r0, Operand(argc_)); // Setup the number of arguments. | 6965 __ mov(r0, Operand(argc_)); // Setup the number of arguments. |
| 6770 __ mov(r2, Operand(0)); | 6966 __ mov(r2, Operand(0)); |
| 6771 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 6967 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 6772 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 6968 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
| 6773 RelocInfo::CODE_TARGET); | 6969 RelocInfo::CODE_TARGET); |
| 6774 } | 6970 } |
| 6775 | 6971 |
| 6776 | 6972 |
| 6777 const char* CompareStub::GetName() { | 6973 const char* CompareStub::GetName() { |
| 6778 switch (cc_) { | 6974 switch (cc_) { |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7461 | 7657 |
| 7462 // Just jump to runtime to add the two strings. | 7658 // Just jump to runtime to add the two strings. |
| 7463 __ bind(&string_add_runtime); | 7659 __ bind(&string_add_runtime); |
| 7464 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); | 7660 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); |
| 7465 } | 7661 } |
| 7466 | 7662 |
| 7467 | 7663 |
| 7468 #undef __ | 7664 #undef __ |
| 7469 | 7665 |
| 7470 } } // namespace v8::internal | 7666 } } // namespace v8::internal |
| OLD | NEW |