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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 CodeGenState state(this); | 194 CodeGenState state(this); |
195 | 195 |
196 // Entry: | 196 // Entry: |
197 // Stack: receiver, arguments, return address. | 197 // Stack: receiver, arguments, return address. |
198 // rbp: caller's frame pointer | 198 // rbp: caller's frame pointer |
199 // rsp: stack pointer | 199 // rsp: stack pointer |
200 // rdi: called JS function | 200 // rdi: called JS function |
201 // rsi: callee's context | 201 // rsi: callee's context |
202 allocator_->Initialize(); | 202 allocator_->Initialize(); |
203 | 203 |
204 if (info->mode() == CompilationInfo::PRIMARY) { | 204 frame_->Enter(); |
205 frame_->Enter(); | |
206 | 205 |
207 // Allocate space for locals and initialize them. | 206 // Allocate space for locals and initialize them. |
208 frame_->AllocateStackSlots(); | 207 frame_->AllocateStackSlots(); |
209 | 208 |
210 // Allocate the local context if needed. | 209 // Allocate the local context if needed. |
211 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 210 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
212 if (heap_slots > 0) { | 211 if (heap_slots > 0) { |
213 Comment cmnt(masm_, "[ allocate local context"); | 212 Comment cmnt(masm_, "[ allocate local context"); |
214 // Allocate local context. | 213 // Allocate local context. |
215 // Get outer context and create a new context based on it. | 214 // Get outer context and create a new context based on it. |
216 frame_->PushFunction(); | 215 frame_->PushFunction(); |
217 Result context; | 216 Result context; |
218 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 217 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
219 FastNewContextStub stub(heap_slots); | 218 FastNewContextStub stub(heap_slots); |
220 context = frame_->CallStub(&stub, 1); | 219 context = frame_->CallStub(&stub, 1); |
221 } else { | 220 } else { |
222 context = frame_->CallRuntime(Runtime::kNewContext, 1); | 221 context = frame_->CallRuntime(Runtime::kNewContext, 1); |
223 } | |
224 | |
225 // Update context local. | |
226 frame_->SaveContextRegister(); | |
227 | |
228 // Verify that the runtime call result and rsi agree. | |
229 if (FLAG_debug_code) { | |
230 __ cmpq(context.reg(), rsi); | |
231 __ Assert(equal, "Runtime::NewContext should end up in rsi"); | |
232 } | |
233 } | 222 } |
234 | 223 |
235 // TODO(1241774): Improve this code: | 224 // Update context local. |
236 // 1) only needed if we have a context | 225 frame_->SaveContextRegister(); |
237 // 2) no need to recompute context ptr every single time | |
238 // 3) don't copy parameter operand code from SlotOperand! | |
239 { | |
240 Comment cmnt2(masm_, "[ copy context parameters into .context"); | |
241 // Note that iteration order is relevant here! If we have the same | |
242 // parameter twice (e.g., function (x, y, x)), and that parameter | |
243 // needs to be copied into the context, it must be the last argument | |
244 // passed to the parameter that needs to be copied. This is a rare | |
245 // case so we don't check for it, instead we rely on the copying | |
246 // order: such a parameter is copied repeatedly into the same | |
247 // context location and thus the last value is what is seen inside | |
248 // the function. | |
249 for (int i = 0; i < scope()->num_parameters(); i++) { | |
250 Variable* par = scope()->parameter(i); | |
251 Slot* slot = par->slot(); | |
252 if (slot != NULL && slot->type() == Slot::CONTEXT) { | |
253 // The use of SlotOperand below is safe in unspilled code | |
254 // because the slot is guaranteed to be a context slot. | |
255 // | |
256 // There are no parameters in the global scope. | |
257 ASSERT(!scope()->is_global_scope()); | |
258 frame_->PushParameterAt(i); | |
259 Result value = frame_->Pop(); | |
260 value.ToRegister(); | |
261 | 226 |
262 // SlotOperand loads context.reg() with the context object | 227 // Verify that the runtime call result and rsi agree. |
263 // stored to, used below in RecordWrite. | 228 if (FLAG_debug_code) { |
264 Result context = allocator_->Allocate(); | 229 __ cmpq(context.reg(), rsi); |
265 ASSERT(context.is_valid()); | 230 __ Assert(equal, "Runtime::NewContext should end up in rsi"); |
266 __ movq(SlotOperand(slot, context.reg()), value.reg()); | |
267 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | |
268 Result scratch = allocator_->Allocate(); | |
269 ASSERT(scratch.is_valid()); | |
270 frame_->Spill(context.reg()); | |
271 frame_->Spill(value.reg()); | |
272 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); | |
273 } | |
274 } | |
275 } | |
276 | |
277 // Store the arguments object. This must happen after context | |
278 // initialization because the arguments object may be stored in | |
279 // the context. | |
280 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | |
281 StoreArgumentsObject(true); | |
282 } | |
283 | |
284 // Initialize ThisFunction reference if present. | |
285 if (scope()->is_function_scope() && scope()->function() != NULL) { | |
286 frame_->Push(Factory::the_hole_value()); | |
287 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); | |
288 } | |
289 } else { | |
290 // When used as the secondary compiler for splitting, rbp, rsi, | |
291 // and rdi have been pushed on the stack. Adjust the virtual | |
292 // frame to match this state. | |
293 frame_->Adjust(3); | |
294 allocator_->Unuse(rdi); | |
295 | |
296 // Bind all the bailout labels to the beginning of the function. | |
297 List<CompilationInfo::Bailout*>* bailouts = info->bailouts(); | |
298 for (int i = 0; i < bailouts->length(); i++) { | |
299 __ bind(bailouts->at(i)->label()); | |
300 } | 231 } |
301 } | 232 } |
302 | 233 |
| 234 // TODO(1241774): Improve this code: |
| 235 // 1) only needed if we have a context |
| 236 // 2) no need to recompute context ptr every single time |
| 237 // 3) don't copy parameter operand code from SlotOperand! |
| 238 { |
| 239 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
| 240 // Note that iteration order is relevant here! If we have the same |
| 241 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 242 // needs to be copied into the context, it must be the last argument |
| 243 // passed to the parameter that needs to be copied. This is a rare |
| 244 // case so we don't check for it, instead we rely on the copying |
| 245 // order: such a parameter is copied repeatedly into the same |
| 246 // context location and thus the last value is what is seen inside |
| 247 // the function. |
| 248 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 249 Variable* par = scope()->parameter(i); |
| 250 Slot* slot = par->slot(); |
| 251 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 252 // The use of SlotOperand below is safe in unspilled code |
| 253 // because the slot is guaranteed to be a context slot. |
| 254 // |
| 255 // There are no parameters in the global scope. |
| 256 ASSERT(!scope()->is_global_scope()); |
| 257 frame_->PushParameterAt(i); |
| 258 Result value = frame_->Pop(); |
| 259 value.ToRegister(); |
| 260 |
| 261 // SlotOperand loads context.reg() with the context object |
| 262 // stored to, used below in RecordWrite. |
| 263 Result context = allocator_->Allocate(); |
| 264 ASSERT(context.is_valid()); |
| 265 __ movq(SlotOperand(slot, context.reg()), value.reg()); |
| 266 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 267 Result scratch = allocator_->Allocate(); |
| 268 ASSERT(scratch.is_valid()); |
| 269 frame_->Spill(context.reg()); |
| 270 frame_->Spill(value.reg()); |
| 271 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); |
| 272 } |
| 273 } |
| 274 } |
| 275 |
| 276 // Store the arguments object. This must happen after context |
| 277 // initialization because the arguments object may be stored in |
| 278 // the context. |
| 279 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
| 280 StoreArgumentsObject(true); |
| 281 } |
| 282 |
| 283 // Initialize ThisFunction reference if present. |
| 284 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 285 frame_->Push(Factory::the_hole_value()); |
| 286 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); |
| 287 } |
| 288 |
303 // Initialize the function return target after the locals are set | 289 // Initialize the function return target after the locals are set |
304 // up, because it needs the expected frame height from the frame. | 290 // up, because it needs the expected frame height from the frame. |
305 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 291 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
306 function_return_is_shadowed_ = false; | 292 function_return_is_shadowed_ = false; |
307 | 293 |
308 // Generate code to 'execute' declarations and initialize functions | 294 // Generate code to 'execute' declarations and initialize functions |
309 // (source elements). In case of an illegal redeclaration we need to | 295 // (source elements). In case of an illegal redeclaration we need to |
310 // handle that instead of processing the declarations. | 296 // handle that instead of processing the declarations. |
311 if (scope()->HasIllegalRedeclaration()) { | 297 if (scope()->HasIllegalRedeclaration()) { |
312 Comment cmnt(masm_, "[ illegal redeclarations"); | 298 Comment cmnt(masm_, "[ illegal redeclarations"); |
(...skipping 12445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12758 #undef __ | 12744 #undef __ |
12759 | 12745 |
12760 void RecordWriteStub::Generate(MacroAssembler* masm) { | 12746 void RecordWriteStub::Generate(MacroAssembler* masm) { |
12761 masm->RecordWriteHelper(object_, addr_, scratch_); | 12747 masm->RecordWriteHelper(object_, addr_, scratch_); |
12762 masm->ret(0); | 12748 masm->ret(0); |
12763 } | 12749 } |
12764 | 12750 |
12765 } } // namespace v8::internal | 12751 } } // namespace v8::internal |
12766 | 12752 |
12767 #endif // V8_TARGET_ARCH_X64 | 12753 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |