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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // o cp: our context | 132 // o cp: our context |
133 // o fp: our caller's frame pointer | 133 // o fp: our caller's frame pointer |
134 // o sp: stack pointer | 134 // o sp: stack pointer |
135 // o ra: return address | 135 // o ra: return address |
136 // | 136 // |
137 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 137 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
138 // frames-mips.h for its layout. | 138 // frames-mips.h for its layout. |
139 void FullCodeGenerator::Generate(CompilationInfo* info) { | 139 void FullCodeGenerator::Generate(CompilationInfo* info) { |
140 ASSERT(info_ == NULL); | 140 ASSERT(info_ == NULL); |
141 info_ = info; | 141 info_ = info; |
| 142 scope_ = info->scope(); |
142 SetFunctionPosition(function()); | 143 SetFunctionPosition(function()); |
143 Comment cmnt(masm_, "[ function compiled by full code generator"); | 144 Comment cmnt(masm_, "[ function compiled by full code generator"); |
144 | 145 |
145 #ifdef DEBUG | 146 #ifdef DEBUG |
146 if (strlen(FLAG_stop_at) > 0 && | 147 if (strlen(FLAG_stop_at) > 0 && |
147 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 148 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
148 __ stop("stop-at"); | 149 __ stop("stop-at"); |
149 } | 150 } |
150 #endif | 151 #endif |
151 | 152 |
152 // Strict mode functions and builtins need to replace the receiver | 153 // Strict mode functions and builtins need to replace the receiver |
153 // with undefined when called as functions (without an explicit | 154 // with undefined when called as functions (without an explicit |
154 // receiver object). t1 is zero for method calls and non-zero for | 155 // receiver object). t1 is zero for method calls and non-zero for |
155 // function calls. | 156 // function calls. |
156 if (info->is_strict_mode() || info->is_native()) { | 157 if (info->is_strict_mode() || info->is_native()) { |
157 Label ok; | 158 Label ok; |
158 __ Branch(&ok, eq, t1, Operand(zero_reg)); | 159 __ Branch(&ok, eq, t1, Operand(zero_reg)); |
159 int receiver_offset = scope()->num_parameters() * kPointerSize; | 160 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
160 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 161 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
161 __ sw(a2, MemOperand(sp, receiver_offset)); | 162 __ sw(a2, MemOperand(sp, receiver_offset)); |
162 __ bind(&ok); | 163 __ bind(&ok); |
163 } | 164 } |
164 | 165 |
165 int locals_count = scope()->num_stack_slots(); | 166 int locals_count = info->scope()->num_stack_slots(); |
166 | 167 |
167 __ Push(ra, fp, cp, a1); | 168 __ Push(ra, fp, cp, a1); |
168 if (locals_count > 0) { | 169 if (locals_count > 0) { |
169 // Load undefined value here, so the value is ready for the loop | 170 // Load undefined value here, so the value is ready for the loop |
170 // below. | 171 // below. |
171 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 172 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
172 } | 173 } |
173 // Adjust fp to point to caller's fp. | 174 // Adjust fp to point to caller's fp. |
174 __ Addu(fp, sp, Operand(2 * kPointerSize)); | 175 __ Addu(fp, sp, Operand(2 * kPointerSize)); |
175 | 176 |
176 { Comment cmnt(masm_, "[ Allocate locals"); | 177 { Comment cmnt(masm_, "[ Allocate locals"); |
177 for (int i = 0; i < locals_count; i++) { | 178 for (int i = 0; i < locals_count; i++) { |
178 __ push(at); | 179 __ push(at); |
179 } | 180 } |
180 } | 181 } |
181 | 182 |
182 bool function_in_register = true; | 183 bool function_in_register = true; |
183 | 184 |
184 // Possibly allocate a local context. | 185 // Possibly allocate a local context. |
185 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 186 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
186 if (heap_slots > 0) { | 187 if (heap_slots > 0) { |
187 Comment cmnt(masm_, "[ Allocate local context"); | 188 Comment cmnt(masm_, "[ Allocate local context"); |
188 // Argument to NewContext is the function, which is in a1. | 189 // Argument to NewContext is the function, which is in a1. |
189 __ push(a1); | 190 __ push(a1); |
190 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 191 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
191 FastNewContextStub stub(heap_slots); | 192 FastNewContextStub stub(heap_slots); |
192 __ CallStub(&stub); | 193 __ CallStub(&stub); |
193 } else { | 194 } else { |
194 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 195 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
195 } | 196 } |
196 function_in_register = false; | 197 function_in_register = false; |
197 // Context is returned in both v0 and cp. It replaces the context | 198 // Context is returned in both v0 and cp. It replaces the context |
198 // passed to us. It's saved in the stack and kept live in cp. | 199 // passed to us. It's saved in the stack and kept live in cp. |
199 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 200 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
200 // Copy any necessary parameters into the context. | 201 // Copy any necessary parameters into the context. |
201 int num_parameters = scope()->num_parameters(); | 202 int num_parameters = info->scope()->num_parameters(); |
202 for (int i = 0; i < num_parameters; i++) { | 203 for (int i = 0; i < num_parameters; i++) { |
203 Slot* slot = scope()->parameter(i)->AsSlot(); | 204 Slot* slot = scope()->parameter(i)->AsSlot(); |
204 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 205 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
205 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 206 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
206 (num_parameters - 1 - i) * kPointerSize; | 207 (num_parameters - 1 - i) * kPointerSize; |
207 // Load parameter from stack. | 208 // Load parameter from stack. |
208 __ lw(a0, MemOperand(fp, parameter_offset)); | 209 __ lw(a0, MemOperand(fp, parameter_offset)); |
209 // Store it in the context. | 210 // Store it in the context. |
210 __ li(a1, Operand(Context::SlotOffset(slot->index()))); | 211 __ li(a1, Operand(Context::SlotOffset(slot->index()))); |
211 __ addu(a2, cp, a1); | 212 __ addu(a2, cp, a1); |
(...skipping 11 matching lines...) Expand all Loading... |
223 if (arguments != NULL) { | 224 if (arguments != NULL) { |
224 // Function uses arguments object. | 225 // Function uses arguments object. |
225 Comment cmnt(masm_, "[ Allocate arguments object"); | 226 Comment cmnt(masm_, "[ Allocate arguments object"); |
226 if (!function_in_register) { | 227 if (!function_in_register) { |
227 // Load this again, if it's used by the local context below. | 228 // Load this again, if it's used by the local context below. |
228 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 229 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
229 } else { | 230 } else { |
230 __ mov(a3, a1); | 231 __ mov(a3, a1); |
231 } | 232 } |
232 // Receiver is just before the parameters on the caller's stack. | 233 // Receiver is just before the parameters on the caller's stack. |
233 int offset = scope()->num_parameters() * kPointerSize; | 234 int num_parameters = info->scope()->num_parameters(); |
| 235 int offset = num_parameters * kPointerSize; |
234 __ Addu(a2, fp, | 236 __ Addu(a2, fp, |
235 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 237 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
236 __ li(a1, Operand(Smi::FromInt(scope()->num_parameters()))); | 238 __ li(a1, Operand(Smi::FromInt(num_parameters))); |
237 __ Push(a3, a2, a1); | 239 __ Push(a3, a2, a1); |
238 | 240 |
239 // Arguments to ArgumentsAccessStub: | 241 // Arguments to ArgumentsAccessStub: |
240 // function, receiver address, parameter count. | 242 // function, receiver address, parameter count. |
241 // The stub will rewrite receiever and parameter count if the previous | 243 // The stub will rewrite receiever and parameter count if the previous |
242 // stack frame was an arguments adapter frame. | 244 // stack frame was an arguments adapter frame. |
243 ArgumentsAccessStub::Type type; | 245 ArgumentsAccessStub::Type type; |
244 if (is_strict_mode()) { | 246 if (is_strict_mode()) { |
245 type = ArgumentsAccessStub::NEW_STRICT; | 247 type = ArgumentsAccessStub::NEW_STRICT; |
246 } else if (function()->has_duplicate_parameters()) { | 248 } else if (function()->has_duplicate_parameters()) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 #ifdef DEBUG | 345 #ifdef DEBUG |
344 // Add a label for checking the size of the code used for returning. | 346 // Add a label for checking the size of the code used for returning. |
345 Label check_exit_codesize; | 347 Label check_exit_codesize; |
346 masm_->bind(&check_exit_codesize); | 348 masm_->bind(&check_exit_codesize); |
347 #endif | 349 #endif |
348 // Make sure that the constant pool is not emitted inside of the return | 350 // Make sure that the constant pool is not emitted inside of the return |
349 // sequence. | 351 // sequence. |
350 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 352 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
351 // Here we use masm_-> instead of the __ macro to avoid the code coverage | 353 // Here we use masm_-> instead of the __ macro to avoid the code coverage |
352 // tool from instrumenting as we rely on the code size here. | 354 // tool from instrumenting as we rely on the code size here. |
353 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; | 355 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; |
354 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); | 356 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); |
355 __ RecordJSReturn(); | 357 __ RecordJSReturn(); |
356 masm_->mov(sp, fp); | 358 masm_->mov(sp, fp); |
357 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); | 359 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); |
358 masm_->Addu(sp, sp, Operand(sp_delta)); | 360 masm_->Addu(sp, sp, Operand(sp_delta)); |
359 masm_->Jump(ra); | 361 masm_->Jump(ra); |
360 } | 362 } |
361 | 363 |
362 #ifdef DEBUG | 364 #ifdef DEBUG |
363 // Check that the size of the code used for returning is large enough | 365 // Check that the size of the code used for returning is large enough |
(...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2132 int arg_count) { | 2134 int arg_count) { |
2133 // Push copy of the first argument or undefined if it doesn't exist. | 2135 // Push copy of the first argument or undefined if it doesn't exist. |
2134 if (arg_count > 0) { | 2136 if (arg_count > 0) { |
2135 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); | 2137 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); |
2136 } else { | 2138 } else { |
2137 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | 2139 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); |
2138 } | 2140 } |
2139 __ push(a1); | 2141 __ push(a1); |
2140 | 2142 |
2141 // Push the receiver of the enclosing function and do runtime call. | 2143 // Push the receiver of the enclosing function and do runtime call. |
2142 __ lw(a1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); | 2144 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2145 __ lw(a1, MemOperand(fp, receiver_offset * kPointerSize)); |
2143 __ push(a1); | 2146 __ push(a1); |
2144 // Push the strict mode flag. | 2147 // Push the strict mode flag. |
2145 __ li(a1, Operand(Smi::FromInt(strict_mode_flag()))); | 2148 __ li(a1, Operand(Smi::FromInt(strict_mode_flag()))); |
2146 __ push(a1); | 2149 __ push(a1); |
2147 | 2150 |
2148 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP | 2151 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP |
2149 ? Runtime::kResolvePossiblyDirectEvalNoLookup | 2152 ? Runtime::kResolvePossiblyDirectEvalNoLookup |
2150 : Runtime::kResolvePossiblyDirectEval, 4); | 2153 : Runtime::kResolvePossiblyDirectEval, 4); |
2151 } | 2154 } |
2152 | 2155 |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2678 } | 2681 } |
2679 | 2682 |
2680 | 2683 |
2681 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2684 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
2682 ASSERT(args->length() == 1); | 2685 ASSERT(args->length() == 1); |
2683 | 2686 |
2684 // ArgumentsAccessStub expects the key in a1 and the formal | 2687 // ArgumentsAccessStub expects the key in a1 and the formal |
2685 // parameter count in a0. | 2688 // parameter count in a0. |
2686 VisitForAccumulatorValue(args->at(0)); | 2689 VisitForAccumulatorValue(args->at(0)); |
2687 __ mov(a1, v0); | 2690 __ mov(a1, v0); |
2688 __ li(a0, Operand(Smi::FromInt(scope()->num_parameters()))); | 2691 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2689 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2692 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
2690 __ CallStub(&stub); | 2693 __ CallStub(&stub); |
2691 context()->Plug(v0); | 2694 context()->Plug(v0); |
2692 } | 2695 } |
2693 | 2696 |
2694 | 2697 |
2695 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { | 2698 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { |
2696 ASSERT(args->length() == 0); | 2699 ASSERT(args->length() == 0); |
2697 | 2700 |
2698 Label exit; | 2701 Label exit; |
2699 // Get the number of formal parameters. | 2702 // Get the number of formal parameters. |
2700 __ li(v0, Operand(Smi::FromInt(scope()->num_parameters()))); | 2703 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2701 | 2704 |
2702 // Check if the calling frame is an arguments adaptor frame. | 2705 // Check if the calling frame is an arguments adaptor frame. |
2703 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2706 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2704 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 2707 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); |
2705 __ Branch(&exit, ne, a3, | 2708 __ Branch(&exit, ne, a3, |
2706 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2709 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2707 | 2710 |
2708 // Arguments adaptor case: Read the arguments length from the | 2711 // Arguments adaptor case: Read the arguments length from the |
2709 // adaptor frame. | 2712 // adaptor frame. |
2710 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2713 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
(...skipping 1520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4231 // as their closure, not the anonymous closure containing the global | 4234 // as their closure, not the anonymous closure containing the global |
4232 // code. Pass a smi sentinel and let the runtime look up the empty | 4235 // code. Pass a smi sentinel and let the runtime look up the empty |
4233 // function. | 4236 // function. |
4234 __ li(at, Operand(Smi::FromInt(0))); | 4237 __ li(at, Operand(Smi::FromInt(0))); |
4235 } else if (scope()->is_eval_scope()) { | 4238 } else if (scope()->is_eval_scope()) { |
4236 // Contexts created by a call to eval have the same closure as the | 4239 // Contexts created by a call to eval have the same closure as the |
4237 // context calling eval, not the anonymous closure containing the eval | 4240 // context calling eval, not the anonymous closure containing the eval |
4238 // code. Fetch it from the context. | 4241 // code. Fetch it from the context. |
4239 __ lw(at, ContextOperand(cp, Context::CLOSURE_INDEX)); | 4242 __ lw(at, ContextOperand(cp, Context::CLOSURE_INDEX)); |
4240 } else { | 4243 } else { |
4241 ASSERT(scope()->is_function_scope()); | 4244 ASSERT(scope()->is_function_scope() || scope()->is_catch_scope()); |
4242 __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4245 __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4243 } | 4246 } |
4244 __ push(at); | 4247 __ push(at); |
4245 } | 4248 } |
4246 | 4249 |
4247 | 4250 |
4248 // ---------------------------------------------------------------------------- | 4251 // ---------------------------------------------------------------------------- |
4249 // Non-local control flow support. | 4252 // Non-local control flow support. |
4250 | 4253 |
4251 void FullCodeGenerator::EnterFinallyBlock() { | 4254 void FullCodeGenerator::EnterFinallyBlock() { |
(...skipping 20 matching lines...) Expand all Loading... |
4272 __ Addu(at, a1, Operand(masm_->CodeObject())); | 4275 __ Addu(at, a1, Operand(masm_->CodeObject())); |
4273 __ Jump(at); | 4276 __ Jump(at); |
4274 } | 4277 } |
4275 | 4278 |
4276 | 4279 |
4277 #undef __ | 4280 #undef __ |
4278 | 4281 |
4279 } } // namespace v8::internal | 4282 } } // namespace v8::internal |
4280 | 4283 |
4281 #endif // V8_TARGET_ARCH_MIPS | 4284 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |