OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 // New scope to get automatic timing calculation. | 245 // New scope to get automatic timing calculation. |
246 { // NOLINT | 246 { // NOLINT |
247 HistogramTimerScope codegen_timer(&Counters::code_generation); | 247 HistogramTimerScope codegen_timer(&Counters::code_generation); |
248 CodeGenState state(this); | 248 CodeGenState state(this); |
249 | 249 |
250 // Entry: | 250 // Entry: |
251 // Stack: receiver, arguments, return address. | 251 // Stack: receiver, arguments, return address. |
252 // ebp: caller's frame pointer | 252 // ebp: caller's frame pointer |
253 // esp: stack pointer | 253 // esp: stack pointer |
254 // edi: called JS function | 254 // edi: called JS function |
255 // esi: callee's context | 255 // esi: callee's context |
Lasse Reichstein
2009/06/26 08:27:48
64-bit register names.
| |
256 allocator_->Initialize(); | 256 allocator_->Initialize(); |
257 frame_->Enter(); | 257 frame_->Enter(); |
258 | 258 |
259 // Allocate space for locals and initialize them. | 259 // Allocate space for locals and initialize them. |
260 frame_->AllocateStackSlots(); | 260 frame_->AllocateStackSlots(); |
261 // Initialize the function return target after the locals are set | 261 // Initialize the function return target after the locals are set |
262 // up, because it needs the expected frame height from the frame. | 262 // up, because it needs the expected frame height from the frame. |
263 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 263 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
264 function_return_is_shadowed_ = false; | 264 function_return_is_shadowed_ = false; |
265 | 265 |
266 // TODO(X64): Add code to handle arguments object and context object. | 266 // Allocate the local context if needed. |
267 if (scope_->num_heap_slots() > 0) { | |
268 Comment cmnt(masm_, "[ allocate local context"); | |
269 // Allocate local context. | |
270 // Get outer context and create a new context based on it. | |
271 frame_->PushFunction(); | |
272 Result context = frame_->CallRuntime(Runtime::kNewContext, 1); | |
273 | |
274 // Update context local. | |
275 frame_->SaveContextRegister(); | |
276 | |
277 // Verify that the runtime call result and esi agree. | |
278 if (FLAG_debug_code) { | |
279 __ cmpq(context.reg(), rsi); | |
280 __ Assert(equal, "Runtime::NewContext should end up in esi"); | |
Lasse Reichstein
2009/06/26 08:27:48
rsi
| |
281 } | |
282 } | |
283 | |
284 // TODO(1241774): Improve this code: | |
285 // 1) only needed if we have a context | |
286 // 2) no need to recompute context ptr every single time | |
287 // 3) don't copy parameter operand code from SlotOperand! | |
288 { | |
289 Comment cmnt2(masm_, "[ copy context parameters into .context"); | |
290 | |
291 // Note that iteration order is relevant here! If we have the same | |
292 // parameter twice (e.g., function (x, y, x)), and that parameter | |
293 // needs to be copied into the context, it must be the last argument | |
294 // passed to the parameter that needs to be copied. This is a rare | |
295 // case so we don't check for it, instead we rely on the copying | |
296 // order: such a parameter is copied repeatedly into the same | |
297 // context location and thus the last value is what is seen inside | |
298 // the function. | |
299 for (int i = 0; i < scope_->num_parameters(); i++) { | |
300 Variable* par = scope_->parameter(i); | |
301 Slot* slot = par->slot(); | |
302 if (slot != NULL && slot->type() == Slot::CONTEXT) { | |
303 // The use of SlotOperand below is safe in unspilled code | |
304 // because the slot is guaranteed to be a context slot. | |
305 // | |
306 // There are no parameters in the global scope. | |
307 ASSERT(!scope_->is_global_scope()); | |
308 frame_->PushParameterAt(i); | |
309 Result value = frame_->Pop(); | |
310 value.ToRegister(); | |
311 | |
312 // SlotOperand loads context.reg() with the context object | |
313 // stored to, used below in RecordWrite. | |
314 Result context = allocator_->Allocate(); | |
315 ASSERT(context.is_valid()); | |
316 __ movq(SlotOperand(slot, context.reg()), value.reg()); | |
317 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | |
318 Result scratch = allocator_->Allocate(); | |
319 ASSERT(scratch.is_valid()); | |
320 frame_->Spill(context.reg()); | |
321 frame_->Spill(value.reg()); | |
322 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); | |
323 } | |
324 } | |
325 } | |
326 | |
327 // Store the arguments object. This must happen after context | |
328 // initialization because the arguments object may be stored in | |
329 // the context. | |
330 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | |
331 StoreArgumentsObject(true); | |
332 } | |
267 | 333 |
268 // Generate code to 'execute' declarations and initialize functions | 334 // Generate code to 'execute' declarations and initialize functions |
269 // (source elements). In case of an illegal redeclaration we need to | 335 // (source elements). In case of an illegal redeclaration we need to |
270 // handle that instead of processing the declarations. | 336 // handle that instead of processing the declarations. |
271 if (scope_->HasIllegalRedeclaration()) { | 337 if (scope_->HasIllegalRedeclaration()) { |
272 Comment cmnt(masm_, "[ illegal redeclarations"); | 338 Comment cmnt(masm_, "[ illegal redeclarations"); |
273 scope_->VisitIllegalRedeclaration(this); | 339 scope_->VisitIllegalRedeclaration(this); |
274 } else { | 340 } else { |
275 Comment cmnt(masm_, "[ declarations"); | 341 Comment cmnt(masm_, "[ declarations"); |
276 ProcessDeclarations(scope_->declarations()); | 342 ProcessDeclarations(scope_->declarations()); |
(...skipping 3052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3329 | 3395 |
3330 void CodeGenerator::LoadGlobalReceiver() { | 3396 void CodeGenerator::LoadGlobalReceiver() { |
3331 Result temp = allocator_->Allocate(); | 3397 Result temp = allocator_->Allocate(); |
3332 Register reg = temp.reg(); | 3398 Register reg = temp.reg(); |
3333 __ movq(reg, GlobalObject()); | 3399 __ movq(reg, GlobalObject()); |
3334 __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset)); | 3400 __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset)); |
3335 frame_->Push(&temp); | 3401 frame_->Push(&temp); |
3336 } | 3402 } |
3337 | 3403 |
3338 | 3404 |
3405 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const { | |
3406 if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | |
3407 ASSERT(scope_->arguments_shadow() != NULL); | |
3408 // We don't want to do lazy arguments allocation for functions that | |
3409 // have heap-allocated contexts, because it interfers with the | |
3410 // uninitialized const tracking in the context objects. | |
3411 return (scope_->num_heap_slots() > 0) | |
3412 ? EAGER_ARGUMENTS_ALLOCATION | |
3413 : LAZY_ARGUMENTS_ALLOCATION; | |
3414 } | |
3415 | |
3416 | |
3417 Result CodeGenerator::StoreArgumentsObject(bool initial) { | |
3418 ArgumentsAllocationMode mode = ArgumentsMode(); | |
3419 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); | |
3420 | |
3421 Comment cmnt(masm_, "[ store arguments object"); | |
3422 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { | |
3423 // When using lazy arguments allocation, we store the hole value | |
3424 // as a sentinel indicating that the arguments object hasn't been | |
3425 // allocated yet. | |
3426 frame_->Push(Factory::the_hole_value()); | |
3427 } else { | |
3428 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | |
3429 frame_->PushFunction(); | |
3430 frame_->PushReceiverSlotAddress(); | |
3431 frame_->Push(Smi::FromInt(scope_->num_parameters())); | |
3432 Result result = frame_->CallStub(&stub, 3); | |
3433 frame_->Push(&result); | |
3434 } | |
3435 | |
3436 { Reference shadow_ref(this, scope_->arguments_shadow()); | |
3437 Reference arguments_ref(this, scope_->arguments()); | |
3438 ASSERT(shadow_ref.is_slot() && arguments_ref.is_slot()); | |
3439 // Here we rely on the convenient property that references to slot | |
3440 // take up zero space in the frame (ie, it doesn't matter that the | |
3441 // stored value is actually below the reference on the frame). | |
3442 JumpTarget done; | |
3443 bool skip_arguments = false; | |
3444 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | |
3445 // We have to skip storing into the arguments slot if it has | |
3446 // already been written to. This can happen if the a function | |
3447 // has a local variable named 'arguments'. | |
3448 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | |
3449 Result arguments = frame_->Pop(); | |
3450 if (arguments.is_constant()) { | |
3451 // We have to skip updating the arguments object if it has | |
3452 // been assigned a proper value. | |
3453 skip_arguments = !arguments.handle()->IsTheHole(); | |
3454 } else { | |
3455 __ Cmp(arguments.reg(), Factory::the_hole_value()); | |
3456 arguments.Unuse(); | |
3457 done.Branch(not_equal); | |
3458 } | |
3459 } | |
3460 if (!skip_arguments) { | |
3461 arguments_ref.SetValue(NOT_CONST_INIT); | |
3462 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | |
3463 } | |
3464 shadow_ref.SetValue(NOT_CONST_INIT); | |
3465 } | |
3466 return frame_->Pop(); | |
3467 } | |
3468 | |
3469 | |
3339 // TODO(1241834): Get rid of this function in favor of just using Load, now | 3470 // TODO(1241834): Get rid of this function in favor of just using Load, now |
3340 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 3471 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global |
3341 // variables w/o reference errors elsewhere. | 3472 // variables w/o reference errors elsewhere. |
3342 void CodeGenerator::LoadTypeofExpression(Expression* x) { | 3473 void CodeGenerator::LoadTypeofExpression(Expression* x) { |
3343 Variable* variable = x->AsVariableProxy()->AsVariable(); | 3474 Variable* variable = x->AsVariableProxy()->AsVariable(); |
3344 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 3475 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
3345 // NOTE: This is somewhat nasty. We force the compiler to load | 3476 // NOTE: This is somewhat nasty. We force the compiler to load |
3346 // the variable as if through '<global>.<variable>' to make sure we | 3477 // the variable as if through '<global>.<variable>' to make sure we |
3347 // do not get reference errors. | 3478 // do not get reference errors. |
3348 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 3479 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
(...skipping 2661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6010 break; | 6141 break; |
6011 default: | 6142 default: |
6012 UNREACHABLE(); | 6143 UNREACHABLE(); |
6013 } | 6144 } |
6014 } | 6145 } |
6015 | 6146 |
6016 | 6147 |
6017 #undef __ | 6148 #undef __ |
6018 | 6149 |
6019 } } // namespace v8::internal | 6150 } } // namespace v8::internal |
OLD | NEW |