Chromium Code Reviews| 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 |