Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 149063: X64 implementation: Add arguments object to context when needed. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698