OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
124 // o cp: our context | 124 // o cp: our context |
125 // o fp: our caller's frame pointer | 125 // o fp: our caller's frame pointer |
126 // o sp: stack pointer | 126 // o sp: stack pointer |
127 // o lr: return address | 127 // o lr: return address |
128 // | 128 // |
129 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 129 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
130 // frames-arm.h for its layout. | 130 // frames-arm.h for its layout. |
131 void FullCodeGenerator::Generate(CompilationInfo* info) { | 131 void FullCodeGenerator::Generate(CompilationInfo* info) { |
132 ASSERT(info_ == NULL); | 132 ASSERT(info_ == NULL); |
133 info_ = info; | 133 info_ = info; |
134 scope_ = info->scope(); | |
134 SetFunctionPosition(function()); | 135 SetFunctionPosition(function()); |
135 Comment cmnt(masm_, "[ function compiled by full code generator"); | 136 Comment cmnt(masm_, "[ function compiled by full code generator"); |
136 | 137 |
137 #ifdef DEBUG | 138 #ifdef DEBUG |
138 if (strlen(FLAG_stop_at) > 0 && | 139 if (strlen(FLAG_stop_at) > 0 && |
139 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 140 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
140 __ stop("stop-at"); | 141 __ stop("stop-at"); |
141 } | 142 } |
142 #endif | 143 #endif |
143 | 144 |
144 // Strict mode functions and builtins need to replace the receiver | 145 // Strict mode functions and builtins need to replace the receiver |
145 // with undefined when called as functions (without an explicit | 146 // with undefined when called as functions (without an explicit |
146 // receiver object). r5 is zero for method calls and non-zero for | 147 // receiver object). r5 is zero for method calls and non-zero for |
147 // function calls. | 148 // function calls. |
148 if (info->is_strict_mode() || info->is_native()) { | 149 if (info->is_strict_mode() || info->is_native()) { |
149 Label ok; | 150 Label ok; |
150 __ cmp(r5, Operand(0)); | 151 __ cmp(r5, Operand(0)); |
151 __ b(eq, &ok); | 152 __ b(eq, &ok); |
152 int receiver_offset = scope()->num_parameters() * kPointerSize; | 153 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
Mads Ager (chromium)
2011/06/30 12:08:32
I'm getting a little confused here. You don't need
Kevin Millikin (Chromium)
2011/06/30 12:30:06
I'm being overly defensive. We are definitely not
| |
153 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 154 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
154 __ str(r2, MemOperand(sp, receiver_offset)); | 155 __ str(r2, MemOperand(sp, receiver_offset)); |
155 __ bind(&ok); | 156 __ bind(&ok); |
156 } | 157 } |
157 | 158 |
158 int locals_count = scope()->num_stack_slots(); | 159 int locals_count = info->scope()->num_stack_slots(); |
159 | 160 |
160 __ Push(lr, fp, cp, r1); | 161 __ Push(lr, fp, cp, r1); |
161 if (locals_count > 0) { | 162 if (locals_count > 0) { |
162 // Load undefined value here, so the value is ready for the loop | 163 // Load undefined value here, so the value is ready for the loop |
163 // below. | 164 // below. |
164 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 165 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
165 } | 166 } |
166 // Adjust fp to point to caller's fp. | 167 // Adjust fp to point to caller's fp. |
167 __ add(fp, sp, Operand(2 * kPointerSize)); | 168 __ add(fp, sp, Operand(2 * kPointerSize)); |
168 | 169 |
169 { Comment cmnt(masm_, "[ Allocate locals"); | 170 { Comment cmnt(masm_, "[ Allocate locals"); |
170 for (int i = 0; i < locals_count; i++) { | 171 for (int i = 0; i < locals_count; i++) { |
171 __ push(ip); | 172 __ push(ip); |
172 } | 173 } |
173 } | 174 } |
174 | 175 |
175 bool function_in_register = true; | 176 bool function_in_register = true; |
176 | 177 |
177 // Possibly allocate a local context. | 178 // Possibly allocate a local context. |
178 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 179 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
179 if (heap_slots > 0) { | 180 if (heap_slots > 0) { |
180 Comment cmnt(masm_, "[ Allocate local context"); | 181 Comment cmnt(masm_, "[ Allocate local context"); |
181 // Argument to NewContext is the function, which is in r1. | 182 // Argument to NewContext is the function, which is in r1. |
182 __ push(r1); | 183 __ push(r1); |
183 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 184 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
184 FastNewContextStub stub(heap_slots); | 185 FastNewContextStub stub(heap_slots); |
185 __ CallStub(&stub); | 186 __ CallStub(&stub); |
186 } else { | 187 } else { |
187 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 188 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
188 } | 189 } |
189 function_in_register = false; | 190 function_in_register = false; |
190 // Context is returned in both r0 and cp. It replaces the context | 191 // Context is returned in both r0 and cp. It replaces the context |
191 // passed to us. It's saved in the stack and kept live in cp. | 192 // passed to us. It's saved in the stack and kept live in cp. |
192 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 193 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
193 // Copy any necessary parameters into the context. | 194 // Copy any necessary parameters into the context. |
194 int num_parameters = scope()->num_parameters(); | 195 int num_parameters = info->scope()->num_parameters(); |
195 for (int i = 0; i < num_parameters; i++) { | 196 for (int i = 0; i < num_parameters; i++) { |
196 Slot* slot = scope()->parameter(i)->AsSlot(); | 197 Slot* slot = scope()->parameter(i)->AsSlot(); |
197 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 198 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
198 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 199 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
199 (num_parameters - 1 - i) * kPointerSize; | 200 (num_parameters - 1 - i) * kPointerSize; |
200 // Load parameter from stack. | 201 // Load parameter from stack. |
201 __ ldr(r0, MemOperand(fp, parameter_offset)); | 202 __ ldr(r0, MemOperand(fp, parameter_offset)); |
202 // Store it in the context. | 203 // Store it in the context. |
203 __ mov(r1, Operand(Context::SlotOffset(slot->index()))); | 204 __ mov(r1, Operand(Context::SlotOffset(slot->index()))); |
204 __ str(r0, MemOperand(cp, r1)); | 205 __ str(r0, MemOperand(cp, r1)); |
(...skipping 10 matching lines...) Expand all Loading... | |
215 if (arguments != NULL) { | 216 if (arguments != NULL) { |
216 // Function uses arguments object. | 217 // Function uses arguments object. |
217 Comment cmnt(masm_, "[ Allocate arguments object"); | 218 Comment cmnt(masm_, "[ Allocate arguments object"); |
218 if (!function_in_register) { | 219 if (!function_in_register) { |
219 // Load this again, if it's used by the local context below. | 220 // Load this again, if it's used by the local context below. |
220 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 221 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
221 } else { | 222 } else { |
222 __ mov(r3, r1); | 223 __ mov(r3, r1); |
223 } | 224 } |
224 // Receiver is just before the parameters on the caller's stack. | 225 // Receiver is just before the parameters on the caller's stack. |
225 int offset = scope()->num_parameters() * kPointerSize; | 226 int num_parameters = info->scope()->num_parameters(); |
227 int offset = num_parameters * kPointerSize; | |
226 __ add(r2, fp, | 228 __ add(r2, fp, |
227 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 229 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
228 __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); | 230 __ mov(r1, Operand(Smi::FromInt(num_parameters))); |
229 __ Push(r3, r2, r1); | 231 __ Push(r3, r2, r1); |
230 | 232 |
231 // Arguments to ArgumentsAccessStub: | 233 // Arguments to ArgumentsAccessStub: |
232 // function, receiver address, parameter count. | 234 // function, receiver address, parameter count. |
233 // The stub will rewrite receiever and parameter count if the previous | 235 // The stub will rewrite receiever and parameter count if the previous |
234 // stack frame was an arguments adapter frame. | 236 // stack frame was an arguments adapter frame. |
235 ArgumentsAccessStub::Type type; | 237 ArgumentsAccessStub::Type type; |
236 if (is_strict_mode()) { | 238 if (is_strict_mode()) { |
237 type = ArgumentsAccessStub::NEW_STRICT; | 239 type = ArgumentsAccessStub::NEW_STRICT; |
238 } else if (function()->has_duplicate_parameters()) { | 240 } else if (function()->has_duplicate_parameters()) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 #ifdef DEBUG | 342 #ifdef DEBUG |
341 // Add a label for checking the size of the code used for returning. | 343 // Add a label for checking the size of the code used for returning. |
342 Label check_exit_codesize; | 344 Label check_exit_codesize; |
343 masm_->bind(&check_exit_codesize); | 345 masm_->bind(&check_exit_codesize); |
344 #endif | 346 #endif |
345 // Make sure that the constant pool is not emitted inside of the return | 347 // Make sure that the constant pool is not emitted inside of the return |
346 // sequence. | 348 // sequence. |
347 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 349 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
348 // Here we use masm_-> instead of the __ macro to avoid the code coverage | 350 // Here we use masm_-> instead of the __ macro to avoid the code coverage |
349 // tool from instrumenting as we rely on the code size here. | 351 // tool from instrumenting as we rely on the code size here. |
350 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; | 352 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; |
351 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); | 353 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); |
352 __ RecordJSReturn(); | 354 __ RecordJSReturn(); |
353 masm_->mov(sp, fp); | 355 masm_->mov(sp, fp); |
354 masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); | 356 masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); |
355 masm_->add(sp, sp, Operand(sp_delta)); | 357 masm_->add(sp, sp, Operand(sp_delta)); |
356 masm_->Jump(lr); | 358 masm_->Jump(lr); |
357 } | 359 } |
358 | 360 |
359 #ifdef DEBUG | 361 #ifdef DEBUG |
360 // Check that the size of the code used for returning is large enough | 362 // Check that the size of the code used for returning is large enough |
(...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2116 int arg_count) { | 2118 int arg_count) { |
2117 // Push copy of the first argument or undefined if it doesn't exist. | 2119 // Push copy of the first argument or undefined if it doesn't exist. |
2118 if (arg_count > 0) { | 2120 if (arg_count > 0) { |
2119 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2121 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
2120 } else { | 2122 } else { |
2121 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 2123 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
2122 } | 2124 } |
2123 __ push(r1); | 2125 __ push(r1); |
2124 | 2126 |
2125 // Push the receiver of the enclosing function and do runtime call. | 2127 // Push the receiver of the enclosing function and do runtime call. |
2126 __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); | 2128 int receiver_offset = 2 + info_->scope()->num_parameters(); |
2129 __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize)); | |
2127 __ push(r1); | 2130 __ push(r1); |
2128 // Push the strict mode flag. | 2131 // Push the strict mode flag. |
2129 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); | 2132 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); |
2130 __ push(r1); | 2133 __ push(r1); |
2131 | 2134 |
2132 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP | 2135 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP |
2133 ? Runtime::kResolvePossiblyDirectEvalNoLookup | 2136 ? Runtime::kResolvePossiblyDirectEvalNoLookup |
2134 : Runtime::kResolvePossiblyDirectEval, 4); | 2137 : Runtime::kResolvePossiblyDirectEval, 4); |
2135 } | 2138 } |
2136 | 2139 |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2668 } | 2671 } |
2669 | 2672 |
2670 | 2673 |
2671 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2674 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
2672 ASSERT(args->length() == 1); | 2675 ASSERT(args->length() == 1); |
2673 | 2676 |
2674 // ArgumentsAccessStub expects the key in edx and the formal | 2677 // ArgumentsAccessStub expects the key in edx and the formal |
2675 // parameter count in r0. | 2678 // parameter count in r0. |
2676 VisitForAccumulatorValue(args->at(0)); | 2679 VisitForAccumulatorValue(args->at(0)); |
2677 __ mov(r1, r0); | 2680 __ mov(r1, r0); |
2678 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); | 2681 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2679 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2682 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
2680 __ CallStub(&stub); | 2683 __ CallStub(&stub); |
2681 context()->Plug(r0); | 2684 context()->Plug(r0); |
2682 } | 2685 } |
2683 | 2686 |
2684 | 2687 |
2685 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { | 2688 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { |
2686 ASSERT(args->length() == 0); | 2689 ASSERT(args->length() == 0); |
2687 | 2690 |
2688 Label exit; | 2691 Label exit; |
2689 // Get the number of formal parameters. | 2692 // Get the number of formal parameters. |
2690 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); | 2693 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2691 | 2694 |
2692 // Check if the calling frame is an arguments adaptor frame. | 2695 // Check if the calling frame is an arguments adaptor frame. |
2693 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2696 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2694 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 2697 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
2695 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2698 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2696 __ b(ne, &exit); | 2699 __ b(ne, &exit); |
2697 | 2700 |
2698 // Arguments adaptor case: Read the arguments length from the | 2701 // Arguments adaptor case: Read the arguments length from the |
2699 // adaptor frame. | 2702 // adaptor frame. |
2700 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2703 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
(...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4226 // as their closure, not the anonymous closure containing the global | 4229 // as their closure, not the anonymous closure containing the global |
4227 // code. Pass a smi sentinel and let the runtime look up the empty | 4230 // code. Pass a smi sentinel and let the runtime look up the empty |
4228 // function. | 4231 // function. |
4229 __ mov(ip, Operand(Smi::FromInt(0))); | 4232 __ mov(ip, Operand(Smi::FromInt(0))); |
4230 } else if (scope()->is_eval_scope()) { | 4233 } else if (scope()->is_eval_scope()) { |
4231 // Contexts created by a call to eval have the same closure as the | 4234 // Contexts created by a call to eval have the same closure as the |
4232 // context calling eval, not the anonymous closure containing the eval | 4235 // context calling eval, not the anonymous closure containing the eval |
4233 // code. Fetch it from the context. | 4236 // code. Fetch it from the context. |
4234 __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); | 4237 __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); |
4235 } else { | 4238 } else { |
4236 ASSERT(scope()->is_function_scope()); | 4239 ASSERT(scope()->is_function_scope() || scope()->is_catch_scope()); |
4237 __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4240 __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4238 } | 4241 } |
4239 __ push(ip); | 4242 __ push(ip); |
4240 } | 4243 } |
4241 | 4244 |
4242 | 4245 |
4243 // ---------------------------------------------------------------------------- | 4246 // ---------------------------------------------------------------------------- |
4244 // Non-local control flow support. | 4247 // Non-local control flow support. |
4245 | 4248 |
4246 void FullCodeGenerator::EnterFinallyBlock() { | 4249 void FullCodeGenerator::EnterFinallyBlock() { |
(...skipping 19 matching lines...) Expand all Loading... | |
4266 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4269 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
4267 __ add(pc, r1, Operand(masm_->CodeObject())); | 4270 __ add(pc, r1, Operand(masm_->CodeObject())); |
4268 } | 4271 } |
4269 | 4272 |
4270 | 4273 |
4271 #undef __ | 4274 #undef __ |
4272 | 4275 |
4273 } } // namespace v8::internal | 4276 } } // namespace v8::internal |
4274 | 4277 |
4275 #endif // V8_TARGET_ARCH_ARM | 4278 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |