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

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

Issue 14423: Experimental: introduce a helper class to delmite a scope where the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years 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/codegen-ia32.h ('k') | src/virtual-frame-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 deferred_(8), 79 deferred_(8),
80 masm_(new MacroAssembler(NULL, buffer_size)), 80 masm_(new MacroAssembler(NULL, buffer_size)),
81 scope_(NULL), 81 scope_(NULL),
82 frame_(NULL), 82 frame_(NULL),
83 allocator_(NULL), 83 allocator_(NULL),
84 cc_reg_(no_condition), 84 cc_reg_(no_condition),
85 state_(NULL), 85 state_(NULL),
86 is_inside_try_(false), 86 is_inside_try_(false),
87 break_stack_height_(0), 87 break_stack_height_(0),
88 loop_nesting_(0), 88 loop_nesting_(0),
89 function_return_is_shadowed_(false) { 89 function_return_is_shadowed_(false),
90 in_spilled_code_(false) {
90 } 91 }
91 92
92 93
93 void CodeGenerator::SetFrame(VirtualFrame* new_frame) { 94 void CodeGenerator::SetFrame(VirtualFrame* new_frame) {
94 if (frame_ != NULL) { 95 if (frame_ != NULL) {
95 frame_->DetachFromCodeGenerator(); 96 frame_->DetachFromCodeGenerator();
96 } 97 }
97 if (new_frame != NULL) { 98 if (new_frame != NULL) {
98 new_frame->AttachToCodeGenerator(); 99 new_frame->AttachToCodeGenerator();
99 } 100 }
(...skipping 26 matching lines...) Expand all
126 ASSERT(scope_ == NULL); 127 ASSERT(scope_ == NULL);
127 scope_ = fun->scope(); 128 scope_ = fun->scope();
128 ASSERT(allocator_ == NULL); 129 ASSERT(allocator_ == NULL);
129 RegisterAllocator register_allocator(this); 130 RegisterAllocator register_allocator(this);
130 allocator_ = &register_allocator; 131 allocator_ = &register_allocator;
131 ASSERT(frame_ == NULL); 132 ASSERT(frame_ == NULL);
132 SetFrame(new VirtualFrame(this)); 133 SetFrame(new VirtualFrame(this));
133 cc_reg_ = no_condition; 134 cc_reg_ = no_condition;
134 function_return_.set_code_generator(this); 135 function_return_.set_code_generator(this);
135 function_return_is_shadowed_ = false; 136 function_return_is_shadowed_ = false;
137 set_in_spilled_code(false);
136 138
137 // Adjust for function-level loop nesting. 139 // Adjust for function-level loop nesting.
138 loop_nesting_ += fun->loop_nesting(); 140 loop_nesting_ += fun->loop_nesting();
139 141
140 { 142 {
141 CodeGenState state(this); 143 CodeGenState state(this);
142 144
143 // Entry 145 // Entry
144 // stack: function, receiver, arguments, return address 146 // stack: function, receiver, arguments, return address
145 // esp: stack pointer 147 // esp: stack pointer
(...skipping 13 matching lines...) Expand all
159 #endif 161 #endif
160 162
161 // Allocate space for locals and initialize them. 163 // Allocate space for locals and initialize them.
162 frame_->AllocateStackSlots(scope_->num_stack_slots()); 164 frame_->AllocateStackSlots(scope_->num_stack_slots());
163 165
164 // Allocate the arguments object and copy the parameters into it. 166 // Allocate the arguments object and copy the parameters into it.
165 if (scope_->arguments() != NULL) { 167 if (scope_->arguments() != NULL) {
166 ASSERT(scope_->arguments_shadow() != NULL); 168 ASSERT(scope_->arguments_shadow() != NULL);
167 Comment cmnt(masm_, "[ Allocate arguments object"); 169 Comment cmnt(masm_, "[ Allocate arguments object");
168 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 170 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
169 frame_->SpillAll(); 171 VirtualFrame::SpilledScope spilled_scope(this);
170 __ lea(eax, frame_->Receiver()); 172 __ lea(eax, frame_->Receiver());
171 frame_->EmitPush(frame_->Function()); 173 frame_->EmitPush(frame_->Function());
172 frame_->EmitPush(eax); 174 frame_->EmitPush(eax);
173 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters()))); 175 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters())));
174 frame_->CallStub(&stub, 3); 176 frame_->CallStub(&stub, 3);
175 frame_->Push(eax); 177 frame_->Push(eax);
176 } 178 }
177 179
178 if (scope_->num_heap_slots() > 0) { 180 if (scope_->num_heap_slots() > 0) {
179 Comment cmnt(masm_, "[ allocate local context"); 181 Comment cmnt(masm_, "[ allocate local context");
180 // Allocate local context. 182 // Allocate local context.
181 // Get outer context and create a new context based on it. 183 // Get outer context and create a new context based on it.
182 frame_->SpillAll(); 184 VirtualFrame::SpilledScope spilled_scope(this);
183 frame_->EmitPush(frame_->Function()); 185 frame_->EmitPush(frame_->Function());
184 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result 186 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result
185 187
186 if (kDebug) { 188 if (kDebug) {
187 JumpTarget verified_true(this); 189 JumpTarget verified_true(this);
188 // Verify eax and esi are the same in debug mode 190 // Verify eax and esi are the same in debug mode
189 __ cmp(eax, Operand(esi)); 191 __ cmp(eax, Operand(esi));
190 verified_true.Branch(equal); 192 verified_true.Branch(equal);
191 __ int3(); 193 __ int3();
192 verified_true.Bind(); 194 verified_true.Bind();
(...skipping 14 matching lines...) Expand all
207 // needs to be copied into the context, it must be the last argument 209 // needs to be copied into the context, it must be the last argument
208 // passed to the parameter that needs to be copied. This is a rare 210 // passed to the parameter that needs to be copied. This is a rare
209 // case so we don't check for it, instead we rely on the copying 211 // case so we don't check for it, instead we rely on the copying
210 // order: such a parameter is copied repeatedly into the same 212 // order: such a parameter is copied repeatedly into the same
211 // context location and thus the last value is what is seen inside 213 // context location and thus the last value is what is seen inside
212 // the function. 214 // the function.
213 for (int i = 0; i < scope_->num_parameters(); i++) { 215 for (int i = 0; i < scope_->num_parameters(); i++) {
214 Variable* par = scope_->parameter(i); 216 Variable* par = scope_->parameter(i);
215 Slot* slot = par->slot(); 217 Slot* slot = par->slot();
216 if (slot != NULL && slot->type() == Slot::CONTEXT) { 218 if (slot != NULL && slot->type() == Slot::CONTEXT) {
217 frame_->SpillAll(); 219 VirtualFrame::SpilledScope spilled_scope(this);
218 ASSERT(!scope_->is_global_scope()); // no parameters in global scope 220 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
219 __ mov(eax, frame_->ParameterAt(i)); 221 __ mov(eax, frame_->ParameterAt(i));
220 // Loads ecx with context; used below in RecordWrite. 222 // Loads ecx with context; used below in RecordWrite.
221 __ mov(SlotOperand(slot, edx), eax); 223 __ mov(SlotOperand(slot, edx), eax);
222 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 224 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
223 __ RecordWrite(edx, offset, eax, ebx); 225 __ RecordWrite(edx, offset, eax, ebx);
224 } 226 }
225 } 227 }
226 } 228 }
227 229
228 // This section stores the pointer to the arguments object that 230 // This section stores the pointer to the arguments object that
229 // was allocated and copied into above. If the address was not 231 // was allocated and copied into above. If the address was not
230 // saved to TOS, we push ecx onto the stack. 232 // saved to TOS, we push ecx onto the stack.
231 // 233 //
232 // Store the arguments object. This must happen after context 234 // Store the arguments object. This must happen after context
233 // initialization because the arguments object may be stored in the 235 // initialization because the arguments object may be stored in the
234 // context. 236 // context.
235 if (scope_->arguments() != NULL) { 237 if (scope_->arguments() != NULL) {
236 frame_->SpillAll(); 238 VirtualFrame::SpilledScope spilled_scope(this);
237 Comment cmnt(masm_, "[ store arguments object"); 239 Comment cmnt(masm_, "[ store arguments object");
238 { Reference shadow_ref(this, scope_->arguments_shadow()); 240 { Reference shadow_ref(this, scope_->arguments_shadow());
239 ASSERT(shadow_ref.is_slot()); 241 ASSERT(shadow_ref.is_slot());
240 { Reference arguments_ref(this, scope_->arguments()); 242 { Reference arguments_ref(this, scope_->arguments());
241 ASSERT(arguments_ref.is_slot()); 243 ASSERT(arguments_ref.is_slot());
242 // Here we rely on the convenient property that references to slot 244 // Here we rely on the convenient property that references to slot
243 // take up zero space in the frame (ie, it doesn't matter that the 245 // take up zero space in the frame (ie, it doesn't matter that the
244 // stored value is actually below the reference on the frame). 246 // stored value is actually below the reference on the frame).
245 arguments_ref.SetValue(NOT_CONST_INIT); 247 arguments_ref.SetValue(NOT_CONST_INIT);
246 } 248 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 // (partially) translated into branches, or it may have set the condition 375 // (partially) translated into branches, or it may have set the condition
374 // code register. If force_cc is set, the value is forced to set the 376 // code register. If force_cc is set, the value is forced to set the
375 // condition code register and no value is pushed. If the condition code 377 // condition code register and no value is pushed. If the condition code
376 // register was set, has_cc() is true and cc_reg_ contains the condition to 378 // register was set, has_cc() is true and cc_reg_ contains the condition to
377 // test for 'true'. 379 // test for 'true'.
378 void CodeGenerator::LoadCondition(Expression* x, 380 void CodeGenerator::LoadCondition(Expression* x,
379 TypeofState typeof_state, 381 TypeofState typeof_state,
380 JumpTarget* true_target, 382 JumpTarget* true_target,
381 JumpTarget* false_target, 383 JumpTarget* false_target,
382 bool force_cc) { 384 bool force_cc) {
385 ASSERT(!in_spilled_code());
383 ASSERT(!has_cc()); 386 ASSERT(!has_cc());
384 387
385 { CodeGenState new_state(this, typeof_state, true_target, false_target); 388 { CodeGenState new_state(this, typeof_state, true_target, false_target);
386 Visit(x); 389 Visit(x);
387 } 390 }
388 391
389 if (force_cc && frame_ != NULL && !has_cc()) { 392 if (force_cc && frame_ != NULL && !has_cc()) {
390 // Convert the TOS value to a boolean in the condition code register. 393 // Convert the TOS value to a boolean in the condition code register.
391 frame_->SpillAll(); 394 VirtualFrame::SpilledScope spilled_scope(this);
392 ToBoolean(true_target, false_target); 395 ToBoolean(true_target, false_target);
393 } 396 }
394 397
395 ASSERT(!force_cc || frame_ == NULL || has_cc()); 398 ASSERT(!force_cc || frame_ == NULL || has_cc());
396 } 399 }
397 400
398 401
399 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 402 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
403 ASSERT(!in_spilled_code());
400 JumpTarget true_target(this); 404 JumpTarget true_target(this);
401 JumpTarget false_target(this); 405 JumpTarget false_target(this);
402 LoadCondition(x, typeof_state, &true_target, &false_target, false); 406 LoadCondition(x, typeof_state, &true_target, &false_target, false);
403 407
404 if (has_cc()) { 408 if (has_cc()) {
405 ASSERT(frame_ != NULL); 409 ASSERT(frame_ != NULL);
406 frame_->SpillAll(); 410 VirtualFrame::SpilledScope spilled_scope(this);
407 // Convert cc_reg_ into a boolean value. 411 // Convert cc_reg_ into a boolean value.
408 JumpTarget loaded(this); 412 JumpTarget loaded(this);
409 JumpTarget materialize_true(this); 413 JumpTarget materialize_true(this);
410 materialize_true.Branch(cc_reg_); 414 materialize_true.Branch(cc_reg_);
411 frame_->EmitPush(Immediate(Factory::false_value())); 415 frame_->EmitPush(Immediate(Factory::false_value()));
412 loaded.Jump(); 416 loaded.Jump();
413 materialize_true.Bind(); 417 materialize_true.Bind();
414 frame_->EmitPush(Immediate(Factory::true_value())); 418 frame_->EmitPush(Immediate(Factory::true_value()));
415 loaded.Bind(); 419 loaded.Bind();
416 cc_reg_ = no_condition; 420 cc_reg_ = no_condition;
417 } 421 }
418 422
419 if (true_target.is_linked() || false_target.is_linked()) { 423 if (true_target.is_linked() || false_target.is_linked()) {
420 // We have at least one condition value that has been "translated" into 424 // We have at least one condition value that has been "translated" into
421 // a branch, thus it needs to be loaded explicitly. 425 // a branch, thus it needs to be loaded explicitly.
422 JumpTarget loaded(this); 426 JumpTarget loaded(this);
423 if (frame_ != NULL) { 427 if (frame_ != NULL) {
424 loaded.Jump(); // Don't lose the current TOS. 428 loaded.Jump(); // Don't lose the current TOS.
425 } 429 }
426 bool both = true_target.is_linked() && false_target.is_linked(); 430 bool both = true_target.is_linked() && false_target.is_linked();
427 // Load "true" if necessary. 431 // Load "true" if necessary.
428 if (true_target.is_linked()) { 432 if (true_target.is_linked()) {
429 true_target.Bind(); 433 true_target.Bind();
430 frame_->SpillAll(); 434 VirtualFrame::SpilledScope spilled_scope(this);
431 frame_->EmitPush(Immediate(Factory::true_value())); 435 frame_->EmitPush(Immediate(Factory::true_value()));
432 } 436 }
433 // If both "true" and "false" need to be reincarnated jump across the 437 // If both "true" and "false" need to be reincarnated jump across the
434 // code for "false". 438 // code for "false".
435 if (both) { 439 if (both) {
436 loaded.Jump(); 440 loaded.Jump();
437 } 441 }
438 // Load "false" if necessary. 442 // Load "false" if necessary.
439 if (false_target.is_linked()) { 443 if (false_target.is_linked()) {
440 false_target.Bind(); 444 false_target.Bind();
441 frame_->SpillAll(); 445 VirtualFrame::SpilledScope spilled_scope(this);
442 frame_->EmitPush(Immediate(Factory::false_value())); 446 frame_->EmitPush(Immediate(Factory::false_value()));
443 } 447 }
444 // A value is loaded on all paths reaching this point. 448 // A value is loaded on all paths reaching this point.
445 loaded.Bind(); 449 loaded.Bind();
446 } 450 }
447 ASSERT(frame_ != NULL); 451 ASSERT(frame_ != NULL);
448 ASSERT(!has_cc()); 452 ASSERT(!has_cc());
449 } 453 }
450 454
451 455
(...skipping 15 matching lines...) Expand all
467 Variable* variable = x->AsVariableProxy()->AsVariable(); 471 Variable* variable = x->AsVariableProxy()->AsVariable();
468 if (variable != NULL && !variable->is_this() && variable->is_global()) { 472 if (variable != NULL && !variable->is_this() && variable->is_global()) {
469 // NOTE: This is somewhat nasty. We force the compiler to load 473 // NOTE: This is somewhat nasty. We force the compiler to load
470 // the variable as if through '<global>.<variable>' to make sure we 474 // the variable as if through '<global>.<variable>' to make sure we
471 // do not get reference errors. 475 // do not get reference errors.
472 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 476 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
473 Literal key(variable->name()); 477 Literal key(variable->name());
474 // TODO(1241834): Fetch the position from the variable instead of using 478 // TODO(1241834): Fetch the position from the variable instead of using
475 // no position. 479 // no position.
476 Property property(&global, &key, RelocInfo::kNoPosition); 480 Property property(&global, &key, RelocInfo::kNoPosition);
477 Load(&property); 481 LoadAndSpill(&property);
478 frame_->SpillAll();
479 } else { 482 } else {
480 Load(x, INSIDE_TYPEOF); 483 LoadAndSpill(x, INSIDE_TYPEOF);
481 frame_->SpillAll();
482 } 484 }
483 } 485 }
484 486
485 487
486 Reference::Reference(CodeGenerator* cgen, Expression* expression) 488 Reference::Reference(CodeGenerator* cgen, Expression* expression)
487 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { 489 : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
488 cgen->LoadReference(this); 490 cgen->LoadReference(this);
489 } 491 }
490 492
491 493
492 Reference::~Reference() { 494 Reference::~Reference() {
493 cgen_->UnloadReference(this); 495 cgen_->UnloadReference(this);
494 } 496 }
495 497
496 498
497 void CodeGenerator::LoadReference(Reference* ref) { 499 void CodeGenerator::LoadReference(Reference* ref) {
498 Comment cmnt(masm_, "[ LoadReference"); 500 Comment cmnt(masm_, "[ LoadReference");
499 Expression* e = ref->expression(); 501 Expression* e = ref->expression();
500 Property* property = e->AsProperty(); 502 Property* property = e->AsProperty();
501 Variable* var = e->AsVariableProxy()->AsVariable(); 503 Variable* var = e->AsVariableProxy()->AsVariable();
502 504
503 if (property != NULL) { 505 if (property != NULL) {
506 VirtualFrame::SpilledScope spilled_scope(this);
504 // The expression is either a property or a variable proxy that rewrites 507 // The expression is either a property or a variable proxy that rewrites
505 // to a property. 508 // to a property.
506 Load(property->obj()); 509 LoadAndSpill(property->obj());
507 frame_->SpillAll();
508 // We use a named reference if the key is a literal symbol, unless it is 510 // We use a named reference if the key is a literal symbol, unless it is
509 // a string that can be legally parsed as an integer. This is because 511 // a string that can be legally parsed as an integer. This is because
510 // otherwise we will not get into the slow case code that handles [] on 512 // otherwise we will not get into the slow case code that handles [] on
511 // String objects. 513 // String objects.
512 Literal* literal = property->key()->AsLiteral(); 514 Literal* literal = property->key()->AsLiteral();
513 uint32_t dummy; 515 uint32_t dummy;
514 if (literal != NULL && 516 if (literal != NULL &&
515 literal->handle()->IsSymbol() && 517 literal->handle()->IsSymbol() &&
516 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { 518 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
517 ref->set_type(Reference::NAMED); 519 ref->set_type(Reference::NAMED);
518 } else { 520 } else {
519 Load(property->key()); 521 LoadAndSpill(property->key());
520 frame_->SpillAll();
521 ref->set_type(Reference::KEYED); 522 ref->set_type(Reference::KEYED);
522 } 523 }
523 } else if (var != NULL) { 524 } else if (var != NULL) {
524 // The expression is a variable proxy that does not rewrite to a 525 // The expression is a variable proxy that does not rewrite to a
525 // property. Global variables are treated as named property references. 526 // property. Global variables are treated as named property references.
526 if (var->is_global()) { 527 if (var->is_global()) {
527 frame_->SpillAll(); 528 VirtualFrame::SpilledScope spilled_scope(this);
528 LoadGlobal(); 529 LoadGlobal();
529 ref->set_type(Reference::NAMED); 530 ref->set_type(Reference::NAMED);
530 } else { 531 } else {
531 ASSERT(var->slot() != NULL); 532 ASSERT(var->slot() != NULL);
532 ref->set_type(Reference::SLOT); 533 ref->set_type(Reference::SLOT);
533 } 534 }
534 } else { 535 } else {
536 VirtualFrame::SpilledScope spilled_scope(this);
535 // Anything else is a runtime error. 537 // Anything else is a runtime error.
536 Load(e); 538 LoadAndSpill(e);
537 frame_->SpillAll();
538 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 539 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
539 } 540 }
540 } 541 }
541 542
542 543
543 void CodeGenerator::UnloadReference(Reference* ref) { 544 void CodeGenerator::UnloadReference(Reference* ref) {
544 // Pop a reference from the stack while preserving TOS. 545 // Pop a reference from the stack while preserving TOS.
545 Comment cmnt(masm_, "[ UnloadReference"); 546 Comment cmnt(masm_, "[ UnloadReference");
546 int size = ref->size(); 547 int size = ref->size();
547 if (size == 1) { 548 if (size == 1) {
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 }; 1263 };
1263 1264
1264 1265
1265 // Call the function just below TOS on the stack with the given 1266 // Call the function just below TOS on the stack with the given
1266 // arguments. The receiver is the TOS. 1267 // arguments. The receiver is the TOS.
1267 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1268 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1268 int position) { 1269 int position) {
1269 // Push the arguments ("left-to-right") on the stack. 1270 // Push the arguments ("left-to-right") on the stack.
1270 int arg_count = args->length(); 1271 int arg_count = args->length();
1271 for (int i = 0; i < arg_count; i++) { 1272 for (int i = 0; i < arg_count; i++) {
1272 Load(args->at(i)); 1273 LoadAndSpill(args->at(i));
1273 frame_->SpillAll();
1274 } 1274 }
1275 1275
1276 // Record the position for debugging purposes. 1276 // Record the position for debugging purposes.
1277 __ RecordPosition(position); 1277 __ RecordPosition(position);
1278 1278
1279 // Use the shared code stub to call the function. 1279 // Use the shared code stub to call the function.
1280 CallFunctionStub call_function(arg_count); 1280 CallFunctionStub call_function(arg_count);
1281 frame_->CallStub(&call_function, arg_count + 1); 1281 frame_->CallStub(&call_function, arg_count + 1);
1282 1282
1283 // Restore context and pop function from the stack. 1283 // Restore context and pop function from the stack.
(...skipping 21 matching lines...) Expand all
1305 // The stack check can trigger the debugger. Before calling it, all 1305 // The stack check can trigger the debugger. Before calling it, all
1306 // values including constants must be spilled to the frame. 1306 // values including constants must be spilled to the frame.
1307 frame_->SpillAll(); 1307 frame_->SpillAll();
1308 frame_->CallStub(&stub, 0); 1308 frame_->CallStub(&stub, 0);
1309 stack_is_ok.Bind(); 1309 stack_is_ok.Bind();
1310 } 1310 }
1311 } 1311 }
1312 1312
1313 1313
1314 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 1314 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
1315 ASSERT(!in_spilled_code());
1315 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { 1316 for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
1316 Visit(statements->at(i)); 1317 Visit(statements->at(i));
1317 } 1318 }
1318 } 1319 }
1319 1320
1320 1321
1321 void CodeGenerator::VisitBlock(Block* node) { 1322 void CodeGenerator::VisitBlock(Block* node) {
1323 ASSERT(!in_spilled_code());
1322 Comment cmnt(masm_, "[ Block"); 1324 Comment cmnt(masm_, "[ Block");
1323 RecordStatementPosition(node); 1325 RecordStatementPosition(node);
1324 node->set_break_stack_height(break_stack_height_); 1326 node->set_break_stack_height(break_stack_height_);
1325 node->break_target()->set_code_generator(this); 1327 node->break_target()->set_code_generator(this);
1326 VisitStatements(node->statements()); 1328 VisitStatements(node->statements());
1327 if (node->break_target()->is_linked()) { 1329 if (node->break_target()->is_linked()) {
1328 node->break_target()->Bind(); 1330 node->break_target()->Bind();
1329 } 1331 }
1330 } 1332 }
1331 1333
1332 1334
1333 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1335 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1334 frame_->SpillAll(); 1336 VirtualFrame::SpilledScope spilled_scope(this);
1335 frame_->EmitPush(Immediate(pairs)); 1337 frame_->EmitPush(Immediate(pairs));
1336 frame_->EmitPush(esi); 1338 frame_->EmitPush(esi);
1337 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1339 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1338 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1340 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1339 // Return value is ignored. 1341 // Return value is ignored.
1340 } 1342 }
1341 1343
1342 1344
1343 void CodeGenerator::VisitDeclaration(Declaration* node) { 1345 void CodeGenerator::VisitDeclaration(Declaration* node) {
1344 Comment cmnt(masm_, "[ Declaration"); 1346 Comment cmnt(masm_, "[ Declaration");
1345 Variable* var = node->proxy()->var(); 1347 Variable* var = node->proxy()->var();
1346 ASSERT(var != NULL); // must have been resolved 1348 ASSERT(var != NULL); // must have been resolved
1347 Slot* slot = var->slot(); 1349 Slot* slot = var->slot();
1348 1350
1349 // If it was not possible to allocate the variable at compile time, 1351 // If it was not possible to allocate the variable at compile time,
1350 // we need to "declare" it at runtime to make sure it actually 1352 // we need to "declare" it at runtime to make sure it actually
1351 // exists in the local context. 1353 // exists in the local context.
1352 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1354 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1353 // Variables with a "LOOKUP" slot were introduced as non-locals 1355 // Variables with a "LOOKUP" slot were introduced as non-locals
1354 // during variable resolution and must have mode DYNAMIC. 1356 // during variable resolution and must have mode DYNAMIC.
1355 ASSERT(var->mode() == Variable::DYNAMIC); 1357 ASSERT(var->mode() == Variable::DYNAMIC);
1356 // For now, just do a runtime call. 1358 // For now, just do a runtime call.
1357 frame_->SpillAll(); 1359 VirtualFrame::SpilledScope spilled_scope(this);
1358 frame_->EmitPush(esi); 1360 frame_->EmitPush(esi);
1359 frame_->EmitPush(Immediate(var->name())); 1361 frame_->EmitPush(Immediate(var->name()));
1360 // Declaration nodes are always introduced in one of two modes. 1362 // Declaration nodes are always introduced in one of two modes.
1361 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1363 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1362 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1364 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1363 frame_->EmitPush(Immediate(Smi::FromInt(attr))); 1365 frame_->EmitPush(Immediate(Smi::FromInt(attr)));
1364 // Push initial value, if any. 1366 // Push initial value, if any.
1365 // Note: For variables we must not push an initial value (such as 1367 // Note: For variables we must not push an initial value (such as
1366 // 'undefined') because we may have a (legal) redeclaration and we 1368 // 'undefined') because we may have a (legal) redeclaration and we
1367 // must not destroy the current value. 1369 // must not destroy the current value.
1368 if (node->mode() == Variable::CONST) { 1370 if (node->mode() == Variable::CONST) {
1369 frame_->EmitPush(Immediate(Factory::the_hole_value())); 1371 frame_->EmitPush(Immediate(Factory::the_hole_value()));
1370 } else if (node->fun() != NULL) { 1372 } else if (node->fun() != NULL) {
1371 Load(node->fun()); 1373 LoadAndSpill(node->fun());
1372 frame_->SpillAll();
1373 } else { 1374 } else {
1374 frame_->EmitPush(Immediate(0)); // no initial value! 1375 frame_->EmitPush(Immediate(0)); // no initial value!
1375 } 1376 }
1376 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 1377 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
1377 // Ignore the return value (declarations are statements). 1378 // Ignore the return value (declarations are statements).
1378 return; 1379 return;
1379 } 1380 }
1380 1381
1381 ASSERT(!var->is_global()); 1382 ASSERT(!var->is_global());
1382 1383
1383 // If we have a function or a constant, we need to initialize the variable. 1384 // If we have a function or a constant, we need to initialize the variable.
1384 Expression* val = NULL; 1385 Expression* val = NULL;
1385 if (node->mode() == Variable::CONST) { 1386 if (node->mode() == Variable::CONST) {
1386 val = new Literal(Factory::the_hole_value()); 1387 val = new Literal(Factory::the_hole_value());
1387 } else { 1388 } else {
1388 val = node->fun(); // NULL if we don't have a function 1389 val = node->fun(); // NULL if we don't have a function
1389 } 1390 }
1390 1391
1391 if (val != NULL) { 1392 if (val != NULL) {
1392 frame_->SpillAll(); 1393 VirtualFrame::SpilledScope spilled_scope(this);
1393 // Set initial value. 1394 // Set initial value.
1394 Reference target(this, node->proxy()); 1395 Reference target(this, node->proxy());
1395 ASSERT(target.is_slot()); 1396 ASSERT(target.is_slot());
1396 Load(val); 1397 LoadAndSpill(val);
1397 frame_->SpillAll();
1398 target.SetValue(NOT_CONST_INIT); 1398 target.SetValue(NOT_CONST_INIT);
1399 // Get rid of the assigned value (declarations are statements). It's 1399 // Get rid of the assigned value (declarations are statements). It's
1400 // safe to pop the value lying on top of the reference before unloading 1400 // safe to pop the value lying on top of the reference before unloading
1401 // the reference itself (which preserves the top of stack) because we 1401 // the reference itself (which preserves the top of stack) because we
1402 // know that it is a zero-sized reference. 1402 // know that it is a zero-sized reference.
1403 frame_->Drop(); 1403 frame_->Drop();
1404 } 1404 }
1405 } 1405 }
1406 1406
1407 1407
1408 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1408 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1409 ASSERT(!in_spilled_code());
1409 Comment cmnt(masm_, "[ ExpressionStatement"); 1410 Comment cmnt(masm_, "[ ExpressionStatement");
1410 RecordStatementPosition(node); 1411 RecordStatementPosition(node);
1411 Expression* expression = node->expression(); 1412 Expression* expression = node->expression();
1412 expression->MarkAsStatement(); 1413 expression->MarkAsStatement();
1413 Load(expression); 1414 Load(expression);
1414 // Remove the lingering expression result from the top of stack. 1415 // Remove the lingering expression result from the top of stack.
1415 frame_->Drop(); 1416 frame_->Drop();
1416 } 1417 }
1417 1418
1418 1419
1419 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1420 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1420 frame_->SpillAll(); 1421 ASSERT(!in_spilled_code());
1422 VirtualFrame::SpilledScope spilled_scope(this);
1421 Comment cmnt(masm_, "// EmptyStatement"); 1423 Comment cmnt(masm_, "// EmptyStatement");
1422 // nothing to do 1424 // nothing to do
1423 } 1425 }
1424 1426
1425 1427
1426 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1428 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1427 frame_->SpillAll(); 1429 ASSERT(!in_spilled_code());
1430 VirtualFrame::SpilledScope spilled_scope(this);
1428 Comment cmnt(masm_, "[ IfStatement"); 1431 Comment cmnt(masm_, "[ IfStatement");
1429 // Generate different code depending on which parts of the if statement 1432 // Generate different code depending on which parts of the if statement
1430 // are present or not. 1433 // are present or not.
1431 bool has_then_stm = node->HasThenStatement(); 1434 bool has_then_stm = node->HasThenStatement();
1432 bool has_else_stm = node->HasElseStatement(); 1435 bool has_else_stm = node->HasElseStatement();
1433 1436
1434 RecordStatementPosition(node); 1437 RecordStatementPosition(node);
1435 JumpTarget exit(this); 1438 JumpTarget exit(this);
1436 if (has_then_stm && has_else_stm) { 1439 if (has_then_stm && has_else_stm) {
1437 JumpTarget then(this); 1440 JumpTarget then(this);
1438 JumpTarget else_(this); 1441 JumpTarget else_(this);
1439 // if (cond) 1442 // if (cond)
1440 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 1443 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1444 &then, &else_, true);
1441 if (frame_ != NULL) { 1445 if (frame_ != NULL) {
1442 // A NULL frame here indicates that the code for the condition cannot 1446 // A NULL frame here indicates that the code for the condition cannot
1443 // fall-through, i.e. it causes unconditional branchs to targets. 1447 // fall-through, i.e. it causes unconditional branchs to targets.
1444 Branch(false, &else_); 1448 Branch(false, &else_);
1445 } 1449 }
1446 // then 1450 // then
1447 if (frame_ != NULL || then.is_linked()) { 1451 if (frame_ != NULL || then.is_linked()) {
1448 // If control flow can reach the then part via fall-through from the 1452 // If control flow can reach the then part via fall-through from the
1449 // test or a branch to the target, compile it. 1453 // test or a branch to the target, compile it.
1450 then.Bind(); 1454 then.Bind();
1451 Visit(node->then_statement()); 1455 VisitAndSpill(node->then_statement());
1452 } 1456 }
1453 if (frame_ != NULL) { 1457 if (frame_ != NULL) {
1454 // A NULL frame here indicates that control did not fall out of the 1458 // A NULL frame here indicates that control did not fall out of the
1455 // then statement, it escaped on all branches. In that case, a jump 1459 // then statement, it escaped on all branches. In that case, a jump
1456 // to the exit label would be dead code (and impossible, because we 1460 // to the exit label would be dead code (and impossible, because we
1457 // don't have a current virtual frame to set at the exit label). 1461 // don't have a current virtual frame to set at the exit label).
1458 frame_->SpillAll();
1459 exit.Jump(); 1462 exit.Jump();
1460 } 1463 }
1461 // else 1464 // else
1462 if (else_.is_linked()) { 1465 if (else_.is_linked()) {
1463 // Control flow for if-then-else does not fall-through to the else 1466 // Control flow for if-then-else does not fall-through to the else
1464 // part, it can only reach here via jump if at all. 1467 // part, it can only reach here via jump if at all.
1465 else_.Bind(); 1468 else_.Bind();
1466 Visit(node->else_statement()); 1469 VisitAndSpill(node->else_statement());
1467 } 1470 }
1468 1471
1469 } else if (has_then_stm) { 1472 } else if (has_then_stm) {
1470 ASSERT(!has_else_stm); 1473 ASSERT(!has_else_stm);
1471 JumpTarget then(this); 1474 JumpTarget then(this);
1472 // if (cond) 1475 // if (cond)
1473 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true); 1476 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1477 &then, &exit, true);
1474 if (frame_ != NULL) { 1478 if (frame_ != NULL) {
1475 Branch(false, &exit); 1479 Branch(false, &exit);
1476 } 1480 }
1477 // then 1481 // then
1478 if (frame_ != NULL || then.is_linked()) { 1482 if (frame_ != NULL || then.is_linked()) {
1479 then.Bind(); 1483 then.Bind();
1480 Visit(node->then_statement()); 1484 VisitAndSpill(node->then_statement());
1481 } 1485 }
1482 1486
1483 } else if (has_else_stm) { 1487 } else if (has_else_stm) {
1484 ASSERT(!has_then_stm); 1488 ASSERT(!has_then_stm);
1485 JumpTarget else_(this); 1489 JumpTarget else_(this);
1486 // if (!cond) 1490 // if (!cond)
1487 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true); 1491 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1492 &exit, &else_, true);
1488 if (frame_ != NULL) { 1493 if (frame_ != NULL) {
1489 Branch(true, &exit); 1494 Branch(true, &exit);
1490 } 1495 }
1491 // else 1496 // else
1492 if (frame_ != NULL || else_.is_linked()) { 1497 if (frame_ != NULL || else_.is_linked()) {
1493 else_.Bind(); 1498 else_.Bind();
1494 Visit(node->else_statement()); 1499 VisitAndSpill(node->else_statement());
1495 } 1500 }
1496 1501
1497 } else { 1502 } else {
1498 ASSERT(!has_then_stm && !has_else_stm); 1503 ASSERT(!has_then_stm && !has_else_stm);
1499 // if (cond) 1504 // if (cond)
1500 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1505 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1506 &exit, &exit, false);
1501 if (frame_ != NULL) { 1507 if (frame_ != NULL) {
1502 frame_->SpillAll();
1503 if (has_cc()) { 1508 if (has_cc()) {
1504 cc_reg_ = no_condition; 1509 cc_reg_ = no_condition;
1505 } else { 1510 } else {
1506 // No cc value set up, that means the boolean was pushed. 1511 // No cc value set up, that means the boolean was pushed.
1507 // Pop it again, since it is not going to be used. 1512 // Pop it again, since it is not going to be used.
1508 frame_->Drop(); 1513 frame_->Drop();
1509 } 1514 }
1510 } 1515 }
1511 } 1516 }
1512 1517
1513 // end 1518 // end
1514 if (exit.is_linked()) { 1519 if (exit.is_linked()) {
1515 exit.Bind(); 1520 exit.Bind();
1516 } 1521 }
1517 } 1522 }
1518 1523
1519 1524
1520 void CodeGenerator::CleanStack(int num_bytes) { 1525 void CodeGenerator::CleanStack(int num_bytes) {
1521 ASSERT(num_bytes % kPointerSize == 0); 1526 ASSERT(num_bytes % kPointerSize == 0);
1522 frame_->Drop(num_bytes / kPointerSize); 1527 frame_->Drop(num_bytes / kPointerSize);
1523 } 1528 }
1524 1529
1525 1530
1526 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1531 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1527 frame_->SpillAll(); 1532 ASSERT(!in_spilled_code());
1533 VirtualFrame::SpilledScope spilled_scope(this);
1528 Comment cmnt(masm_, "[ ContinueStatement"); 1534 Comment cmnt(masm_, "[ ContinueStatement");
1529 RecordStatementPosition(node); 1535 RecordStatementPosition(node);
1530 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1536 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1531 node->target()->continue_target()->Jump(); 1537 node->target()->continue_target()->Jump();
1532 } 1538 }
1533 1539
1534 1540
1535 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1541 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1536 frame_->SpillAll(); 1542 ASSERT(!in_spilled_code());
1543 VirtualFrame::SpilledScope spilled_scope(this);
1537 Comment cmnt(masm_, "[ BreakStatement"); 1544 Comment cmnt(masm_, "[ BreakStatement");
1538 RecordStatementPosition(node); 1545 RecordStatementPosition(node);
1539 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1546 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1540 node->target()->break_target()->Jump(); 1547 node->target()->break_target()->Jump();
1541 } 1548 }
1542 1549
1543 1550
1544 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1551 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1545 frame_->SpillAll(); 1552 ASSERT(!in_spilled_code());
1553 VirtualFrame::SpilledScope spilled_scope(this);
1546 Comment cmnt(masm_, "[ ReturnStatement"); 1554 Comment cmnt(masm_, "[ ReturnStatement");
1547 RecordStatementPosition(node); 1555 RecordStatementPosition(node);
1548 Load(node->expression()); 1556 LoadAndSpill(node->expression());
1549 frame_->SpillAll();
1550 1557
1551 // Move the function result into eax 1558 // Move the function result into eax
1552 frame_->EmitPop(eax); 1559 frame_->EmitPop(eax);
1553 1560
1554 // If we're inside a try statement or the return instruction 1561 // If we're inside a try statement or the return instruction
1555 // sequence has been generated, we just jump to that 1562 // sequence has been generated, we just jump to that
1556 // point. Otherwise, we generate the return instruction sequence and 1563 // point. Otherwise, we generate the return instruction sequence and
1557 // bind the function return label. 1564 // bind the function return label.
1558 if (is_inside_try_ || function_return_.is_bound()) { 1565 if (is_inside_try_ || function_return_.is_bound()) {
1559 function_return_.Jump(); 1566 function_return_.Jump();
(...skipping 16 matching lines...) Expand all
1576 1583
1577 // Check that the size of the code used for returning matches what is 1584 // Check that the size of the code used for returning matches what is
1578 // expected by the debugger. 1585 // expected by the debugger.
1579 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, 1586 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1580 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); 1587 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1581 } 1588 }
1582 } 1589 }
1583 1590
1584 1591
1585 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1592 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1586 frame_->SpillAll(); 1593 ASSERT(!in_spilled_code());
1594 VirtualFrame::SpilledScope spilled_scope(this);
1587 Comment cmnt(masm_, "[ WithEnterStatement"); 1595 Comment cmnt(masm_, "[ WithEnterStatement");
1588 RecordStatementPosition(node); 1596 RecordStatementPosition(node);
1589 Load(node->expression()); 1597 LoadAndSpill(node->expression());
1590 frame_->SpillAll();
1591 frame_->CallRuntime(Runtime::kPushContext, 1); 1598 frame_->CallRuntime(Runtime::kPushContext, 1);
1592 1599
1593 if (kDebug) { 1600 if (kDebug) {
1594 JumpTarget verified_true(this); 1601 JumpTarget verified_true(this);
1595 // Verify eax and esi are the same in debug mode 1602 // Verify eax and esi are the same in debug mode
1596 __ cmp(eax, Operand(esi)); 1603 __ cmp(eax, Operand(esi));
1597 verified_true.Branch(equal); 1604 verified_true.Branch(equal);
1598 __ int3(); 1605 __ int3();
1599 verified_true.Bind(); 1606 verified_true.Bind();
1600 } 1607 }
1601 1608
1602 // Update context local. 1609 // Update context local.
1603 __ mov(frame_->Context(), esi); 1610 __ mov(frame_->Context(), esi);
1604 } 1611 }
1605 1612
1606 1613
1607 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1614 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1608 frame_->SpillAll(); 1615 ASSERT(!in_spilled_code());
1616 VirtualFrame::SpilledScope spilled_scope(this);
1609 Comment cmnt(masm_, "[ WithExitStatement"); 1617 Comment cmnt(masm_, "[ WithExitStatement");
1610 // Pop context. 1618 // Pop context.
1611 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); 1619 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
1612 // Update context local. 1620 // Update context local.
1613 __ mov(frame_->Context(), esi); 1621 __ mov(frame_->Context(), esi);
1614 } 1622 }
1615 1623
1616 1624
1617 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { 1625 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
1618 return kFastSwitchMaxOverheadFactor; 1626 return kFastSwitchMaxOverheadFactor;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1685 1693
1686 for (int i = 0, entry_pos = table_start.label()->pos(); 1694 for (int i = 0, entry_pos = table_start.label()->pos();
1687 i < range; 1695 i < range;
1688 i++, entry_pos += sizeof(uint32_t)) { 1696 i++, entry_pos += sizeof(uint32_t)) {
1689 __ WriteInternalReference(entry_pos, *case_targets[i]->label()); 1697 __ WriteInternalReference(entry_pos, *case_targets[i]->label());
1690 } 1698 }
1691 } 1699 }
1692 1700
1693 1701
1694 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1702 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1695 frame_->SpillAll(); 1703 ASSERT(!in_spilled_code());
1704 VirtualFrame::SpilledScope spilled_scope(this);
1696 Comment cmnt(masm_, "[ SwitchStatement"); 1705 Comment cmnt(masm_, "[ SwitchStatement");
1697 RecordStatementPosition(node); 1706 RecordStatementPosition(node);
1698 node->set_break_stack_height(break_stack_height_); 1707 node->set_break_stack_height(break_stack_height_);
1699 node->break_target()->set_code_generator(this); 1708 node->break_target()->set_code_generator(this);
1700 1709
1701 Load(node->tag()); 1710 LoadAndSpill(node->tag());
1702 frame_->SpillAll();
1703 1711
1704 if (TryGenerateFastCaseSwitchStatement(node)) { 1712 if (TryGenerateFastCaseSwitchStatement(node)) {
1705 return; 1713 return;
1706 } 1714 }
1707 1715
1708 JumpTarget next_test(this); 1716 JumpTarget next_test(this);
1709 JumpTarget fall_through(this); 1717 JumpTarget fall_through(this);
1710 JumpTarget default_entry(this); 1718 JumpTarget default_entry(this);
1711 JumpTarget default_exit(this); 1719 JumpTarget default_exit(this);
1712 ZoneList<CaseClause*>* cases = node->cases(); 1720 ZoneList<CaseClause*>* cases = node->cases();
1713 int length = cases->length(); 1721 int length = cases->length();
1714 CaseClause* default_clause = NULL; 1722 CaseClause* default_clause = NULL;
1715 1723
1716 for (int i = 0; i < length; i++) { 1724 for (int i = 0; i < length; i++) {
1717 CaseClause* clause = cases->at(i); 1725 CaseClause* clause = cases->at(i);
1718 if (clause->is_default()) { 1726 if (clause->is_default()) {
1719 // Remember the default clause and compile it at the end. 1727 // Remember the default clause and compile it at the end.
1720 default_clause = clause; 1728 default_clause = clause;
1721 continue; 1729 continue;
1722 } 1730 }
1723 1731
1724 Comment cmnt(masm_, "[ Case clause"); 1732 Comment cmnt(masm_, "[ Case clause");
1725 // Compile the test. 1733 // Compile the test.
1726 next_test.Bind(); 1734 next_test.Bind();
1727 next_test.Unuse(); 1735 next_test.Unuse();
1728 // Duplicate TOS. 1736 // Duplicate TOS.
1729 __ mov(eax, frame_->Top()); 1737 __ mov(eax, frame_->Top());
1730 frame_->EmitPush(eax); 1738 frame_->EmitPush(eax);
1731 Load(clause->label()); 1739 LoadAndSpill(clause->label());
1732 frame_->SpillAll();
1733 Comparison(equal, true); 1740 Comparison(equal, true);
1734 Branch(false, &next_test); 1741 Branch(false, &next_test);
1735 1742
1736 // Before entering the body from the test, remove the switch value from 1743 // Before entering the body from the test, remove the switch value from
1737 // the stack. 1744 // the stack.
1738 frame_->Drop(); 1745 frame_->Drop();
1739 1746
1740 // Label the body so that fall through is enabled. 1747 // Label the body so that fall through is enabled.
1741 if (i > 0 && cases->at(i - 1)->is_default()) { 1748 if (i > 0 && cases->at(i - 1)->is_default()) {
1742 default_exit.Bind(); 1749 default_exit.Bind();
1743 } else { 1750 } else {
1744 fall_through.Bind(); 1751 fall_through.Bind();
1745 fall_through.Unuse(); 1752 fall_through.Unuse();
1746 } 1753 }
1747 VisitStatements(clause->statements()); 1754 VisitStatementsAndSpill(clause->statements());
1748 1755
1749 // If control flow can fall through from the body, jump to the next body 1756 // If control flow can fall through from the body, jump to the next body
1750 // or the end of the statement. 1757 // or the end of the statement.
1751 if (frame_ != NULL) { 1758 if (frame_ != NULL) {
1752 frame_->SpillAll();
1753 if (i < length - 1 && cases->at(i + 1)->is_default()) { 1759 if (i < length - 1 && cases->at(i + 1)->is_default()) {
1754 default_entry.Jump(); 1760 default_entry.Jump();
1755 } else { 1761 } else {
1756 fall_through.Jump(); 1762 fall_through.Jump();
1757 } 1763 }
1758 } 1764 }
1759 } 1765 }
1760 1766
1761 // The final "test" removes the switch value. 1767 // The final "test" removes the switch value.
1762 next_test.Bind(); 1768 next_test.Bind();
1763 frame_->Drop(); 1769 frame_->Drop();
1764 1770
1765 // If there is a default clause, compile it. 1771 // If there is a default clause, compile it.
1766 if (default_clause != NULL) { 1772 if (default_clause != NULL) {
1767 Comment cmnt(masm_, "[ Default clause"); 1773 Comment cmnt(masm_, "[ Default clause");
1768 default_entry.Bind(); 1774 default_entry.Bind();
1769 VisitStatements(default_clause->statements()); 1775 VisitStatementsAndSpill(default_clause->statements());
1770 if (frame_ != NULL) { 1776 if (frame_ != NULL) {
1771 frame_->SpillAll();
1772 } 1777 }
1773 // If control flow can fall out of the default and there is a case after 1778 // If control flow can fall out of the default and there is a case after
1774 // it, jump to that case's body. 1779 // it, jump to that case's body.
1775 if (frame_ != NULL && default_exit.is_bound()) { 1780 if (frame_ != NULL && default_exit.is_bound()) {
1776 default_exit.Jump(); 1781 default_exit.Jump();
1777 } 1782 }
1778 } 1783 }
1779 1784
1780 if (fall_through.is_linked()) { 1785 if (fall_through.is_linked()) {
1781 fall_through.Bind(); 1786 fall_through.Bind();
1782 } 1787 }
1783 1788
1784 if (node->break_target()->is_linked()) { 1789 if (node->break_target()->is_linked()) {
1785 node->break_target()->Bind(); 1790 node->break_target()->Bind();
1786 } 1791 }
1787 } 1792 }
1788 1793
1789 1794
1790 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1795 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1796 ASSERT(!in_spilled_code());
1791 Comment cmnt(masm_, "[ LoopStatement"); 1797 Comment cmnt(masm_, "[ LoopStatement");
1792 RecordStatementPosition(node); 1798 RecordStatementPosition(node);
1793 node->set_break_stack_height(break_stack_height_); 1799 node->set_break_stack_height(break_stack_height_);
1794 node->break_target()->set_code_generator(this); 1800 node->break_target()->set_code_generator(this);
1795 node->continue_target()->set_code_generator(this); 1801 node->continue_target()->set_code_generator(this);
1796 1802
1797 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 1803 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
1798 // known result for the test expression, with no side effects. 1804 // known result for the test expression, with no side effects.
1799 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1805 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
1800 if (node->cond() == NULL) { 1806 if (node->cond() == NULL) {
1801 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1807 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1802 info = ALWAYS_TRUE; 1808 info = ALWAYS_TRUE;
1803 } else { 1809 } else {
1804 Literal* lit = node->cond()->AsLiteral(); 1810 Literal* lit = node->cond()->AsLiteral();
1805 if (lit != NULL) { 1811 if (lit != NULL) {
1806 if (lit->IsTrue()) { 1812 if (lit->IsTrue()) {
1807 info = ALWAYS_TRUE; 1813 info = ALWAYS_TRUE;
1808 } else if (lit->IsFalse()) { 1814 } else if (lit->IsFalse()) {
1809 info = ALWAYS_FALSE; 1815 info = ALWAYS_FALSE;
1810 } 1816 }
1811 } 1817 }
1812 } 1818 }
1813 1819
1814 switch (node->type()) { 1820 switch (node->type()) {
1815 case LoopStatement::DO_LOOP: { 1821 case LoopStatement::DO_LOOP: {
1816 // The new code generator does not yet compile do loops. 1822 // The new code generator does not yet compile do loops.
1817 frame_->SpillAll(); 1823 VirtualFrame::SpilledScope spilled_scope(this);
1818 JumpTarget body(this); 1824 JumpTarget body(this);
1819 IncrementLoopNesting(); 1825 IncrementLoopNesting();
1820 // Label the body. 1826 // Label the body.
1821 if (info == ALWAYS_TRUE) { 1827 if (info == ALWAYS_TRUE) {
1822 node->continue_target()->Bind(); 1828 node->continue_target()->Bind();
1823 } else if (info == ALWAYS_FALSE) { 1829 } else if (info == ALWAYS_FALSE) {
1824 // There is no need, we will never jump back. 1830 // There is no need, we will never jump back.
1825 } else { 1831 } else {
1826 ASSERT(info == DONT_KNOW); 1832 ASSERT(info == DONT_KNOW);
1827 body.Bind(); 1833 body.Bind();
1828 } 1834 }
1829 CheckStack(); // TODO(1222600): ignore if body contains calls. 1835 CheckStack(); // TODO(1222600): ignore if body contains calls.
1830 Visit(node->body()); 1836 VisitAndSpill(node->body());
1831 if (frame_ != NULL) {
1832 frame_->SpillAll();
1833 }
1834 1837
1835 // Compile the "test". 1838 // Compile the "test".
1836 if (info == ALWAYS_TRUE) { 1839 if (info == ALWAYS_TRUE) {
1837 if (frame_ != NULL) { 1840 if (frame_ != NULL) {
1838 // If control flow can fall off the end of the body, jump back to 1841 // If control flow can fall off the end of the body, jump back to
1839 // the top. 1842 // the top.
1840 node->continue_target()->Jump(); 1843 node->continue_target()->Jump();
1841 } 1844 }
1842 } else if (info == ALWAYS_FALSE) { 1845 } else if (info == ALWAYS_FALSE) {
1843 // If we have a continue in the body, we only have to bind its jump 1846 // If we have a continue in the body, we only have to bind its jump
1844 // target. 1847 // target.
1845 if (node->continue_target()->is_linked()) { 1848 if (node->continue_target()->is_linked()) {
1846 node->continue_target()->Bind(); 1849 node->continue_target()->Bind();
1847 } 1850 }
1848 } else { 1851 } else {
1849 ASSERT(info == DONT_KNOW); 1852 ASSERT(info == DONT_KNOW);
1850 // We have to compile the test expression if it can be reached by 1853 // We have to compile the test expression if it can be reached by
1851 // control flow falling out of the body or via continue. 1854 // control flow falling out of the body or via continue.
1852 if (frame_ != NULL || node->continue_target()->is_linked()) { 1855 if (frame_ != NULL || node->continue_target()->is_linked()) {
1853 node->continue_target()->Bind(); 1856 node->continue_target()->Bind();
1854 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 1857 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1855 &body, node->break_target(), true); 1858 &body, node->break_target(), true);
1856 if (frame_ != NULL) { 1859 if (frame_ != NULL) {
1857 // A NULL frame here indicates that control flow did not fall 1860 // A NULL frame here indicates that control flow did not fall
1858 // out of the test expression. 1861 // out of the test expression.
1859 Branch(true, &body); 1862 Branch(true, &body);
1860 } 1863 }
1861 } 1864 }
1862 } 1865 }
1863 break; 1866 break;
1864 } 1867 }
1865 1868
1866 case LoopStatement::WHILE_LOOP: { 1869 case LoopStatement::WHILE_LOOP: {
1867 // The new code generator does not yet compile while loops. 1870 // The new code generator does not yet compile while loops.
1868 frame_->SpillAll(); 1871 VirtualFrame::SpilledScope spilled_scope(this);
1869 JumpTarget body(this); 1872 JumpTarget body(this);
1870 IncrementLoopNesting(); 1873 IncrementLoopNesting();
1871 // Generate the loop header. 1874 // Generate the loop header.
1872 if (info == ALWAYS_TRUE) { 1875 if (info == ALWAYS_TRUE) {
1873 // Merely label the body with the continue target. 1876 // Merely label the body with the continue target.
1874 node->continue_target()->Bind(); 1877 node->continue_target()->Bind();
1875 } else if (info == ALWAYS_FALSE) { 1878 } else if (info == ALWAYS_FALSE) {
1876 // There is no need to even compile the test or body. 1879 // There is no need to even compile the test or body.
1877 break; 1880 break;
1878 } else { 1881 } else {
1879 // Compile the test labeled with the continue target and label the 1882 // Compile the test labeled with the continue target and label the
1880 // body with the body target. 1883 // body with the body target.
1881 ASSERT(info == DONT_KNOW); 1884 ASSERT(info == DONT_KNOW);
1882 node->continue_target()->Bind(); 1885 node->continue_target()->Bind();
1883 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 1886 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1884 &body, node->break_target(), true); 1887 &body, node->break_target(), true);
1885 if (frame_ != NULL) { 1888 if (frame_ != NULL) {
1886 // A NULL frame indicates that control did not fall out of the 1889 // A NULL frame indicates that control did not fall out of the
1887 // test expression. 1890 // test expression.
1888 Branch(false, node->break_target()); 1891 Branch(false, node->break_target());
1889 } 1892 }
1890 if (frame_ != NULL || body.is_linked()) { 1893 if (frame_ != NULL || body.is_linked()) {
1891 body.Bind(); 1894 body.Bind();
1892 } 1895 }
1893 } 1896 }
1894 if (frame_ != NULL) { 1897 if (frame_ != NULL) {
1895 CheckStack(); // TODO(1222600): ignore if body contains calls. 1898 CheckStack(); // TODO(1222600): ignore if body contains calls.
1896 Visit(node->body()); 1899 VisitAndSpill(node->body());
1897 1900
1898 // If control flow can fall out of the body, jump back to the top. 1901 // If control flow can fall out of the body, jump back to the top.
1899 if (frame_ != NULL) { 1902 if (frame_ != NULL) {
1900 frame_->SpillAll();
1901 node->continue_target()->Jump(); 1903 node->continue_target()->Jump();
1902 } 1904 }
1903 } 1905 }
1904 break; 1906 break;
1905 } 1907 }
1906 1908
1907 case LoopStatement::FOR_LOOP: { 1909 case LoopStatement::FOR_LOOP: {
1908 JumpTarget loop(this); 1910 JumpTarget loop(this);
1909 JumpTarget body(this); 1911 JumpTarget body(this);
1910 if (node->init() != NULL) { 1912 if (node->init() != NULL) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1968 } 1970 }
1969 1971
1970 DecrementLoopNesting(); 1972 DecrementLoopNesting();
1971 if (node->break_target()->is_linked()) { 1973 if (node->break_target()->is_linked()) {
1972 node->break_target()->Bind(); 1974 node->break_target()->Bind();
1973 } 1975 }
1974 } 1976 }
1975 1977
1976 1978
1977 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1979 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1978 frame_->SpillAll(); 1980 ASSERT(!in_spilled_code());
1981 VirtualFrame::SpilledScope spilled_scope(this);
1979 Comment cmnt(masm_, "[ ForInStatement"); 1982 Comment cmnt(masm_, "[ ForInStatement");
1980 RecordStatementPosition(node); 1983 RecordStatementPosition(node);
1981 1984
1982 // We keep stuff on the stack while the body is executing. 1985 // We keep stuff on the stack while the body is executing.
1983 // Record it, so that a break/continue crossing this statement 1986 // Record it, so that a break/continue crossing this statement
1984 // can restore the stack. 1987 // can restore the stack.
1985 const int kForInStackSize = 5 * kPointerSize; 1988 const int kForInStackSize = 5 * kPointerSize;
1986 break_stack_height_ += kForInStackSize; 1989 break_stack_height_ += kForInStackSize;
1987 node->set_break_stack_height(break_stack_height_); 1990 node->set_break_stack_height(break_stack_height_);
1988 node->break_target()->set_code_generator(this); 1991 node->break_target()->set_code_generator(this);
1989 node->continue_target()->set_code_generator(this); 1992 node->continue_target()->set_code_generator(this);
1990 1993
1991 JumpTarget primitive(this); 1994 JumpTarget primitive(this);
1992 JumpTarget jsobject(this); 1995 JumpTarget jsobject(this);
1993 JumpTarget fixed_array(this); 1996 JumpTarget fixed_array(this);
1994 JumpTarget entry(this); 1997 JumpTarget entry(this);
1995 JumpTarget end_del_check(this); 1998 JumpTarget end_del_check(this);
1996 JumpTarget cleanup(this); 1999 JumpTarget cleanup(this);
1997 JumpTarget exit(this); 2000 JumpTarget exit(this);
1998 2001
1999 // Get the object to enumerate over (converted to JSObject). 2002 // Get the object to enumerate over (converted to JSObject).
2000 Load(node->enumerable()); 2003 LoadAndSpill(node->enumerable());
2001 frame_->SpillAll();
2002 2004
2003 // Both SpiderMonkey and kjs ignore null and undefined in contrast 2005 // Both SpiderMonkey and kjs ignore null and undefined in contrast
2004 // to the specification. 12.6.4 mandates a call to ToObject. 2006 // to the specification. 12.6.4 mandates a call to ToObject.
2005 frame_->EmitPop(eax); 2007 frame_->EmitPop(eax);
2006 2008
2007 // eax: value to be iterated over 2009 // eax: value to be iterated over
2008 __ cmp(eax, Factory::undefined_value()); 2010 __ cmp(eax, Factory::undefined_value());
2009 exit.Branch(equal); 2011 exit.Branch(equal);
2010 __ cmp(eax, Factory::null_value()); 2012 __ cmp(eax, Factory::null_value());
2011 exit.Branch(equal); 2013 exit.Branch(equal);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2133 frame_->Drop(); 2135 frame_->Drop();
2134 } 2136 }
2135 } 2137 }
2136 } 2138 }
2137 // Discard the i'th entry pushed above or else the remainder of the 2139 // Discard the i'th entry pushed above or else the remainder of the
2138 // reference, whichever is currently on top of the stack. 2140 // reference, whichever is currently on top of the stack.
2139 frame_->Drop(); 2141 frame_->Drop();
2140 2142
2141 // Body. 2143 // Body.
2142 CheckStack(); // TODO(1222600): ignore if body contains calls. 2144 CheckStack(); // TODO(1222600): ignore if body contains calls.
2143 Visit(node->body()); 2145 VisitAndSpill(node->body());
2144 if (frame_ != NULL) {
2145 frame_->SpillAll();
2146 }
2147 2146
2148 // Next. 2147 // Next.
2149 node->continue_target()->Bind(); 2148 node->continue_target()->Bind();
2150 frame_->EmitPop(eax); 2149 frame_->EmitPop(eax);
2151 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2150 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2152 frame_->EmitPush(eax); 2151 frame_->EmitPush(eax);
2153 entry.Jump(); 2152 entry.Jump();
2154 2153
2155 // Cleanup. 2154 // Cleanup.
2156 cleanup.Bind(); 2155 cleanup.Bind();
2157 node->break_target()->Bind(); 2156 node->break_target()->Bind();
2158 frame_->Drop(5); 2157 frame_->Drop(5);
2159 2158
2160 // Exit. 2159 // Exit.
2161 exit.Bind(); 2160 exit.Bind();
2162 2161
2163 break_stack_height_ -= kForInStackSize; 2162 break_stack_height_ -= kForInStackSize;
2164 } 2163 }
2165 2164
2166 2165
2167 void CodeGenerator::VisitTryCatch(TryCatch* node) { 2166 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2168 frame_->SpillAll(); 2167 ASSERT(!in_spilled_code());
2168 VirtualFrame::SpilledScope spilled_scope(this);
2169 Comment cmnt(masm_, "[ TryCatch"); 2169 Comment cmnt(masm_, "[ TryCatch");
2170 2170
2171 JumpTarget try_block(this); 2171 JumpTarget try_block(this);
2172 JumpTarget exit(this); 2172 JumpTarget exit(this);
2173 2173
2174 try_block.Call(); 2174 try_block.Call();
2175 // --- Catch block --- 2175 // --- Catch block ---
2176 frame_->EmitPush(eax); 2176 frame_->EmitPush(eax);
2177 2177
2178 // Store the caught exception in the catch variable. 2178 // Store the caught exception in the catch variable.
2179 { Reference ref(this, node->catch_var()); 2179 { Reference ref(this, node->catch_var());
2180 ASSERT(ref.is_slot()); 2180 ASSERT(ref.is_slot());
2181 // Load the exception to the top of the stack. Here we make use of the 2181 // Load the exception to the top of the stack. Here we make use of the
2182 // convenient property that it doesn't matter whether a value is 2182 // convenient property that it doesn't matter whether a value is
2183 // immediately on top of or underneath a zero-sized reference. 2183 // immediately on top of or underneath a zero-sized reference.
2184 ref.SetValue(NOT_CONST_INIT); 2184 ref.SetValue(NOT_CONST_INIT);
2185 } 2185 }
2186 2186
2187 // Remove the exception from the stack. 2187 // Remove the exception from the stack.
2188 frame_->Drop(); 2188 frame_->Drop();
2189 2189
2190 VisitStatements(node->catch_block()->statements()); 2190 VisitStatementsAndSpill(node->catch_block()->statements());
2191 if (frame_ != NULL) { 2191 if (frame_ != NULL) {
2192 frame_->SpillAll();
2193 exit.Jump(); 2192 exit.Jump();
2194 } 2193 }
2195 2194
2196 2195
2197 // --- Try block --- 2196 // --- Try block ---
2198 try_block.Bind(); 2197 try_block.Bind();
2199 2198
2200 frame_->PushTryHandler(TRY_CATCH_HANDLER); 2199 frame_->PushTryHandler(TRY_CATCH_HANDLER);
2201 int handler_height = frame_->height(); 2200 int handler_height = frame_->height();
2202 2201
2203 // Shadow the jump targets for all escapes from the try block, including 2202 // Shadow the jump targets for all escapes from the try block, including
2204 // returns. During shadowing, the original target is hidden as the 2203 // returns. During shadowing, the original target is hidden as the
2205 // ShadowTarget and operations on the original actually affect the 2204 // ShadowTarget and operations on the original actually affect the
2206 // shadowing target. 2205 // shadowing target.
2207 // 2206 //
2208 // We should probably try to unify the escaping targets and the return 2207 // We should probably try to unify the escaping targets and the return
2209 // target. 2208 // target.
2210 int nof_escapes = node->escaping_targets()->length(); 2209 int nof_escapes = node->escaping_targets()->length();
2211 List<ShadowTarget*> shadows(1 + nof_escapes); 2210 List<ShadowTarget*> shadows(1 + nof_escapes);
2212 shadows.Add(new ShadowTarget(&function_return_)); 2211 shadows.Add(new ShadowTarget(&function_return_));
2213 for (int i = 0; i < nof_escapes; i++) { 2212 for (int i = 0; i < nof_escapes; i++) {
2214 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); 2213 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
2215 } 2214 }
2216 bool function_return_was_shadowed = function_return_is_shadowed_; 2215 bool function_return_was_shadowed = function_return_is_shadowed_;
2217 function_return_is_shadowed_ = true; 2216 function_return_is_shadowed_ = true;
2218 2217
2219 // Generate code for the statements in the try block. 2218 // Generate code for the statements in the try block.
2220 bool was_inside_try = is_inside_try_; 2219 bool was_inside_try = is_inside_try_;
2221 is_inside_try_ = true; 2220 is_inside_try_ = true;
2222 VisitStatements(node->try_block()->statements()); 2221 VisitStatementsAndSpill(node->try_block()->statements());
2223 if (frame_ != NULL) {
2224 frame_->SpillAll();
2225 }
2226 is_inside_try_ = was_inside_try; 2222 is_inside_try_ = was_inside_try;
2227 2223
2228 // Stop the introduced shadowing and count the number of required unlinks. 2224 // Stop the introduced shadowing and count the number of required unlinks.
2229 // After shadowing stops, the original targets are unshadowed and the 2225 // After shadowing stops, the original targets are unshadowed and the
2230 // ShadowTargets represent the formerly shadowing targets. 2226 // ShadowTargets represent the formerly shadowing targets.
2231 int nof_unlinks = 0; 2227 int nof_unlinks = 0;
2232 for (int i = 0; i <= nof_escapes; i++) { 2228 for (int i = 0; i <= nof_escapes; i++) {
2233 shadows[i]->StopShadowing(); 2229 shadows[i]->StopShadowing();
2234 if (shadows[i]->is_linked()) nof_unlinks++; 2230 if (shadows[i]->is_linked()) nof_unlinks++;
2235 } 2231 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 // next_sp popped. 2274 // next_sp popped.
2279 shadows[i]->original_target()->Jump(); 2275 shadows[i]->original_target()->Jump();
2280 } 2276 }
2281 } 2277 }
2282 2278
2283 exit.Bind(); 2279 exit.Bind();
2284 } 2280 }
2285 2281
2286 2282
2287 void CodeGenerator::VisitTryFinally(TryFinally* node) { 2283 void CodeGenerator::VisitTryFinally(TryFinally* node) {
2288 frame_->SpillAll(); 2284 ASSERT(!in_spilled_code());
2285 VirtualFrame::SpilledScope spilled_scope(this);
2289 Comment cmnt(masm_, "[ TryFinally"); 2286 Comment cmnt(masm_, "[ TryFinally");
2290 2287
2291 // State: Used to keep track of reason for entering the finally 2288 // State: Used to keep track of reason for entering the finally
2292 // block. Should probably be extended to hold information for 2289 // block. Should probably be extended to hold information for
2293 // break/continue from within the try block. 2290 // break/continue from within the try block.
2294 enum { FALLING, THROWING, JUMPING }; 2291 enum { FALLING, THROWING, JUMPING };
2295 2292
2296 JumpTarget unlink(this); 2293 JumpTarget unlink(this);
2297 JumpTarget try_block(this); 2294 JumpTarget try_block(this);
2298 JumpTarget finally_block(this); 2295 JumpTarget finally_block(this);
(...skipping 24 matching lines...) Expand all
2323 shadows.Add(new ShadowTarget(&function_return_)); 2320 shadows.Add(new ShadowTarget(&function_return_));
2324 for (int i = 0; i < nof_escapes; i++) { 2321 for (int i = 0; i < nof_escapes; i++) {
2325 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); 2322 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
2326 } 2323 }
2327 bool function_return_was_shadowed = function_return_is_shadowed_; 2324 bool function_return_was_shadowed = function_return_is_shadowed_;
2328 function_return_is_shadowed_ = true; 2325 function_return_is_shadowed_ = true;
2329 2326
2330 // Generate code for the statements in the try block. 2327 // Generate code for the statements in the try block.
2331 bool was_inside_try = is_inside_try_; 2328 bool was_inside_try = is_inside_try_;
2332 is_inside_try_ = true; 2329 is_inside_try_ = true;
2333 VisitStatements(node->try_block()->statements()); 2330 VisitStatementsAndSpill(node->try_block()->statements());
2334 if (frame_ != NULL) {
2335 frame_->SpillAll();
2336 }
2337 is_inside_try_ = was_inside_try; 2331 is_inside_try_ = was_inside_try;
2338 2332
2339 // Stop the introduced shadowing and count the number of required unlinks. 2333 // Stop the introduced shadowing and count the number of required unlinks.
2340 // After shadowing stops, the original targets are unshadowed and the 2334 // After shadowing stops, the original targets are unshadowed and the
2341 // ShadowTargets represent the formerly shadowing targets. 2335 // ShadowTargets represent the formerly shadowing targets.
2342 int nof_unlinks = 0; 2336 int nof_unlinks = 0;
2343 for (int i = 0; i <= nof_escapes; i++) { 2337 for (int i = 0; i <= nof_escapes; i++) {
2344 shadows[i]->StopShadowing(); 2338 shadows[i]->StopShadowing();
2345 if (shadows[i]->is_linked()) nof_unlinks++; 2339 if (shadows[i]->is_linked()) nof_unlinks++;
2346 } 2340 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 frame_->EmitPush(ecx); 2393 frame_->EmitPush(ecx);
2400 2394
2401 // We keep two elements on the stack - the (possibly faked) result 2395 // We keep two elements on the stack - the (possibly faked) result
2402 // and the state - while evaluating the finally block. Record it, so 2396 // and the state - while evaluating the finally block. Record it, so
2403 // that a break/continue crossing this statement can restore the 2397 // that a break/continue crossing this statement can restore the
2404 // stack. 2398 // stack.
2405 const int kFinallyStackSize = 2 * kPointerSize; 2399 const int kFinallyStackSize = 2 * kPointerSize;
2406 break_stack_height_ += kFinallyStackSize; 2400 break_stack_height_ += kFinallyStackSize;
2407 2401
2408 // Generate code for the statements in the finally block. 2402 // Generate code for the statements in the finally block.
2409 VisitStatements(node->finally_block()->statements()); 2403 VisitStatementsAndSpill(node->finally_block()->statements());
2410 2404
2411 break_stack_height_ -= kFinallyStackSize; 2405 break_stack_height_ -= kFinallyStackSize;
2412 if (frame_ != NULL) { 2406 if (frame_ != NULL) {
2413 frame_->SpillAll();
2414 JumpTarget exit(this); 2407 JumpTarget exit(this);
2415 // Restore state and return value or faked TOS. 2408 // Restore state and return value or faked TOS.
2416 frame_->EmitPop(ecx); 2409 frame_->EmitPop(ecx);
2417 frame_->EmitPop(eax); 2410 frame_->EmitPop(eax);
2418 2411
2419 // Generate code to jump to the right destination for all used 2412 // Generate code to jump to the right destination for all used
2420 // (formerly) shadowing targets. 2413 // (formerly) shadowing targets.
2421 for (int i = 0; i <= nof_escapes; i++) { 2414 for (int i = 0; i <= nof_escapes; i++) {
2422 if (shadows[i]->is_bound()) { 2415 if (shadows[i]->is_bound()) {
2423 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 2416 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
2424 shadows[i]->original_target()->Branch(equal); 2417 shadows[i]->original_target()->Branch(equal);
2425 } 2418 }
2426 } 2419 }
2427 2420
2428 // Check if we need to rethrow the exception. 2421 // Check if we need to rethrow the exception.
2429 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); 2422 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
2430 exit.Branch(not_equal); 2423 exit.Branch(not_equal);
2431 2424
2432 // Rethrow exception. 2425 // Rethrow exception.
2433 frame_->EmitPush(eax); // undo pop from above 2426 frame_->EmitPush(eax); // undo pop from above
2434 frame_->CallRuntime(Runtime::kReThrow, 1); 2427 frame_->CallRuntime(Runtime::kReThrow, 1);
2435 2428
2436 // Done. 2429 // Done.
2437 exit.Bind(); 2430 exit.Bind();
2438 } 2431 }
2439 } 2432 }
2440 2433
2441 2434
2442 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2435 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2443 frame_->SpillAll(); 2436 ASSERT(!in_spilled_code());
2437 VirtualFrame::SpilledScope spilled_scope(this);
2444 Comment cmnt(masm_, "[ DebuggerStatement"); 2438 Comment cmnt(masm_, "[ DebuggerStatement");
2445 RecordStatementPosition(node); 2439 RecordStatementPosition(node);
2446 frame_->CallRuntime(Runtime::kDebugBreak, 0); 2440 frame_->CallRuntime(Runtime::kDebugBreak, 0);
2447 // Ignore the return value. 2441 // Ignore the return value.
2448 } 2442 }
2449 2443
2450 2444
2451 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2445 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2452 ASSERT(boilerplate->IsBoilerplate()); 2446 ASSERT(boilerplate->IsBoilerplate());
2453 2447
2454 // Push the boilerplate on the stack. 2448 // Push the boilerplate on the stack.
2455 frame_->EmitPush(Immediate(boilerplate)); 2449 frame_->EmitPush(Immediate(boilerplate));
2456 2450
2457 // Create a new closure. 2451 // Create a new closure.
2458 frame_->EmitPush(esi); 2452 frame_->EmitPush(esi);
2459 frame_->CallRuntime(Runtime::kNewClosure, 2); 2453 frame_->CallRuntime(Runtime::kNewClosure, 2);
2460 frame_->EmitPush(eax); 2454 frame_->EmitPush(eax);
2461 } 2455 }
2462 2456
2463 2457
2464 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2458 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2465 frame_->SpillAll(); 2459 VirtualFrame::SpilledScope spilled_scope(this);
2466 Comment cmnt(masm_, "[ FunctionLiteral"); 2460 Comment cmnt(masm_, "[ FunctionLiteral");
2467 2461
2468 // Build the function boilerplate and instantiate it. 2462 // Build the function boilerplate and instantiate it.
2469 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2463 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2470 // Check for stack-overflow exception. 2464 // Check for stack-overflow exception.
2471 if (HasStackOverflow()) return; 2465 if (HasStackOverflow()) return;
2472 InstantiateBoilerplate(boilerplate); 2466 InstantiateBoilerplate(boilerplate);
2473 } 2467 }
2474 2468
2475 2469
2476 void CodeGenerator::VisitFunctionBoilerplateLiteral( 2470 void CodeGenerator::VisitFunctionBoilerplateLiteral(
2477 FunctionBoilerplateLiteral* node) { 2471 FunctionBoilerplateLiteral* node) {
2478 frame_->SpillAll(); 2472 VirtualFrame::SpilledScope spilled_scope(this);
2479 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2473 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2480 InstantiateBoilerplate(node->boilerplate()); 2474 InstantiateBoilerplate(node->boilerplate());
2481 } 2475 }
2482 2476
2483 2477
2484 void CodeGenerator::VisitConditional(Conditional* node) { 2478 void CodeGenerator::VisitConditional(Conditional* node) {
2485 frame_->SpillAll(); 2479 VirtualFrame::SpilledScope spilled_scope(this);
2486 Comment cmnt(masm_, "[ Conditional"); 2480 Comment cmnt(masm_, "[ Conditional");
2487 JumpTarget then(this); 2481 JumpTarget then(this);
2488 JumpTarget else_(this); 2482 JumpTarget else_(this);
2489 JumpTarget exit(this); 2483 JumpTarget exit(this);
2490 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 2484 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
2485 &then, &else_, true);
2491 if (frame_ != NULL) { 2486 if (frame_ != NULL) {
2492 Branch(false, &else_); 2487 Branch(false, &else_);
2493 } 2488 }
2494 if (frame_ != NULL || then.is_linked()) { 2489 if (frame_ != NULL || then.is_linked()) {
2495 then.Bind(); 2490 then.Bind();
2496 Load(node->then_expression(), typeof_state()); 2491 LoadAndSpill(node->then_expression(), typeof_state());
2497 frame_->SpillAll();
2498 exit.Jump(); 2492 exit.Jump();
2499 } 2493 }
2500 if (else_.is_linked()) { 2494 if (else_.is_linked()) {
2501 else_.Bind(); 2495 else_.Bind();
2502 Load(node->else_expression(), typeof_state()); 2496 LoadAndSpill(node->else_expression(), typeof_state());
2503 frame_->SpillAll();
2504 } 2497 }
2505 exit.Bind(); 2498 exit.Bind();
2506 } 2499 }
2507 2500
2508 2501
2509 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2502 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2510 if (slot->type() == Slot::LOOKUP) { 2503 if (slot->type() == Slot::LOOKUP) {
2511 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2504 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2512 2505
2513 // For now, just do a runtime call. 2506 // For now, just do a runtime call.
2514 frame_->SpillAll(); 2507 VirtualFrame::SpilledScope spilled_scope(this);
2515 frame_->EmitPush(esi); 2508 frame_->EmitPush(esi);
2516 frame_->EmitPush(Immediate(slot->var()->name())); 2509 frame_->EmitPush(Immediate(slot->var()->name()));
2517 2510
2518 if (typeof_state == INSIDE_TYPEOF) { 2511 if (typeof_state == INSIDE_TYPEOF) {
2519 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2512 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2520 } else { 2513 } else {
2521 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2514 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2522 } 2515 }
2523 frame_->EmitPush(eax); 2516 frame_->EmitPush(eax);
2524 2517
2525 } else { 2518 } else {
2526 // Note: We would like to keep the assert below, but it fires because of 2519 // Note: We would like to keep the assert below, but it fires because of
2527 // some nasty code in LoadTypeofExpression() which should be removed... 2520 // some nasty code in LoadTypeofExpression() which should be removed...
2528 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2521 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2529 if (slot->var()->mode() == Variable::CONST) { 2522 if (slot->var()->mode() == Variable::CONST) {
2530 // Const slots may contain 'the hole' value (the constant hasn't been 2523 // Const slots may contain 'the hole' value (the constant hasn't been
2531 // initialized yet) which needs to be converted into the 'undefined' 2524 // initialized yet) which needs to be converted into the 'undefined'
2532 // value. 2525 // value.
2533 frame_->SpillAll(); 2526 VirtualFrame::SpilledScope spilled_scope(this);
2534 Comment cmnt(masm_, "[ Load const"); 2527 Comment cmnt(masm_, "[ Load const");
2535 JumpTarget exit(this); 2528 JumpTarget exit(this);
2536 __ mov(eax, SlotOperand(slot, ecx)); 2529 __ mov(eax, SlotOperand(slot, ecx));
2537 __ cmp(eax, Factory::the_hole_value()); 2530 __ cmp(eax, Factory::the_hole_value());
2538 exit.Branch(not_equal); 2531 exit.Branch(not_equal);
2539 __ mov(eax, Factory::undefined_value()); 2532 __ mov(eax, Factory::undefined_value());
2540 exit.Bind(); 2533 exit.Bind();
2541 frame_->EmitPush(eax); 2534 frame_->EmitPush(eax);
2542 } else { 2535 } else {
2543 if (slot->type() == Slot::PARAMETER) { 2536 if (slot->type() == Slot::PARAMETER) {
2544 frame_->LoadParameterAt(slot->index()); 2537 frame_->LoadParameterAt(slot->index());
2545 } else if (slot->type() == Slot::LOCAL) { 2538 } else if (slot->type() == Slot::LOCAL) {
2546 frame_->LoadLocalAt(slot->index()); 2539 frame_->LoadLocalAt(slot->index());
2547 } else { 2540 } else {
2548 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach 2541 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
2549 // here. 2542 // here.
2550 ASSERT(slot->type() == Slot::CONTEXT); 2543 ASSERT(slot->type() == Slot::CONTEXT);
2551 frame_->SpillAll(); 2544 VirtualFrame::SpilledScope spilled_scope(this);
2552 frame_->EmitPush(SlotOperand(slot, ecx)); 2545 frame_->EmitPush(SlotOperand(slot, ecx));
2553 } 2546 }
2554 } 2547 }
2555 } 2548 }
2556 } 2549 }
2557 2550
2558 2551
2559 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 2552 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
2560 if (slot->type() == Slot::LOOKUP) { 2553 if (slot->type() == Slot::LOOKUP) {
2561 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2554 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2562 2555
2563 // For now, just do a runtime call. 2556 // For now, just do a runtime call.
2564 frame_->SpillAll(); 2557 VirtualFrame::SpilledScope spilled_scope(this);
2565 frame_->EmitPush(frame_->Context()); 2558 frame_->EmitPush(frame_->Context());
2566 frame_->EmitPush(Immediate(slot->var()->name())); 2559 frame_->EmitPush(Immediate(slot->var()->name()));
2567 2560
2568 if (init_state == CONST_INIT) { 2561 if (init_state == CONST_INIT) {
2569 // Same as the case for a normal store, but ignores attribute 2562 // Same as the case for a normal store, but ignores attribute
2570 // (e.g. READ_ONLY) of context slot so that we can initialize const 2563 // (e.g. READ_ONLY) of context slot so that we can initialize const
2571 // properties (introduced via eval("const foo = (some expr);")). Also, 2564 // properties (introduced via eval("const foo = (some expr);")). Also,
2572 // uses the current function context instead of the top context. 2565 // uses the current function context instead of the top context.
2573 // 2566 //
2574 // Note that we must declare the foo upon entry of eval(), via a 2567 // Note that we must declare the foo upon entry of eval(), via a
(...skipping 17 matching lines...) Expand all
2592 } else { 2585 } else {
2593 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2586 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2594 2587
2595 JumpTarget exit(this); 2588 JumpTarget exit(this);
2596 if (init_state == CONST_INIT) { 2589 if (init_state == CONST_INIT) {
2597 ASSERT(slot->var()->mode() == Variable::CONST); 2590 ASSERT(slot->var()->mode() == Variable::CONST);
2598 // Only the first const initialization must be executed (the slot 2591 // Only the first const initialization must be executed (the slot
2599 // still contains 'the hole' value). When the assignment is executed, 2592 // still contains 'the hole' value). When the assignment is executed,
2600 // the code is identical to a normal store (see below). 2593 // the code is identical to a normal store (see below).
2601 Comment cmnt(masm_, "[ Init const"); 2594 Comment cmnt(masm_, "[ Init const");
2602 frame_->SpillAll(); 2595 VirtualFrame::SpilledScope spilled_scope(this);
2603 __ mov(eax, SlotOperand(slot, ecx)); 2596 __ mov(eax, SlotOperand(slot, ecx));
2604 __ cmp(eax, Factory::the_hole_value()); 2597 __ cmp(eax, Factory::the_hole_value());
2605 exit.Branch(not_equal); 2598 exit.Branch(not_equal);
2606 } 2599 }
2607 2600
2608 // We must execute the store. Storing a variable must keep the (new) 2601 // We must execute the store. Storing a variable must keep the (new)
2609 // value on the stack. This is necessary for compiling assignment 2602 // value on the stack. This is necessary for compiling assignment
2610 // expressions. 2603 // expressions.
2611 // 2604 //
2612 // Note: We will reach here even with slot->var()->mode() == 2605 // Note: We will reach here even with slot->var()->mode() ==
2613 // Variable::CONST because of const declarations which will initialize 2606 // Variable::CONST because of const declarations which will initialize
2614 // consts to 'the hole' value and by doing so, end up calling this code. 2607 // consts to 'the hole' value and by doing so, end up calling this code.
2615 if (slot->type() == Slot::PARAMETER) { 2608 if (slot->type() == Slot::PARAMETER) {
2616 frame_->StoreToParameterAt(slot->index()); 2609 frame_->StoreToParameterAt(slot->index());
2617 } else if (slot->type() == Slot::LOCAL) { 2610 } else if (slot->type() == Slot::LOCAL) {
2618 frame_->StoreToLocalAt(slot->index()); 2611 frame_->StoreToLocalAt(slot->index());
2619 } else { 2612 } else {
2620 // The other slot types (LOOKUP and GLOBAL) cannot reach here. 2613 // The other slot types (LOOKUP and GLOBAL) cannot reach here.
2621 ASSERT(slot->type() == Slot::CONTEXT); 2614 ASSERT(slot->type() == Slot::CONTEXT);
2622 frame_->SpillAll(); 2615 VirtualFrame::SpilledScope spilled_scope(this);
2623 frame_->EmitPop(eax); 2616 frame_->EmitPop(eax);
2624 __ mov(SlotOperand(slot, ecx), eax); 2617 __ mov(SlotOperand(slot, ecx), eax);
2625 frame_->EmitPush(eax); // RecordWrite may destroy the value in eax. 2618 frame_->EmitPush(eax); // RecordWrite may destroy the value in eax.
2626 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2619 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
2627 __ RecordWrite(ecx, offset, eax, ebx); 2620 __ RecordWrite(ecx, offset, eax, ebx);
2628 } 2621 }
2629 2622
2630 // If we definitely did not jump over the assignment, we do not need 2623 // If we definitely did not jump over the assignment, we do not need
2631 // to bind the exit label. Doing so can defeat peephole 2624 // to bind the exit label. Doing so can defeat peephole
2632 // optimization. 2625 // optimization.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2706 // RegExp pattern (2). 2699 // RegExp pattern (2).
2707 __ push(Immediate(node_->pattern())); 2700 __ push(Immediate(node_->pattern()));
2708 // RegExp flags (3). 2701 // RegExp flags (3).
2709 __ push(Immediate(node_->flags())); 2702 __ push(Immediate(node_->flags()));
2710 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2703 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2711 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx 2704 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx
2712 } 2705 }
2713 2706
2714 2707
2715 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2708 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2716 frame_->SpillAll(); 2709 VirtualFrame::SpilledScope spilled_scope(this);
2717 Comment cmnt(masm_, "[ RegExp Literal"); 2710 Comment cmnt(masm_, "[ RegExp Literal");
2718 RegExpDeferred* deferred = new RegExpDeferred(this, node); 2711 RegExpDeferred* deferred = new RegExpDeferred(this, node);
2719 2712
2720 // Retrieve the literal array and check the allocated entry. 2713 // Retrieve the literal array and check the allocated entry.
2721 2714
2722 // Load the function of this activation. 2715 // Load the function of this activation.
2723 __ mov(ecx, frame_->Function()); 2716 __ mov(ecx, frame_->Function());
2724 2717
2725 // Load the literals array of the function. 2718 // Load the literals array of the function.
2726 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2719 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2767 // Literal index (1). 2760 // Literal index (1).
2768 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2761 __ push(Immediate(Smi::FromInt(node_->literal_index())));
2769 // Constant properties (2). 2762 // Constant properties (2).
2770 __ push(Immediate(node_->constant_properties())); 2763 __ push(Immediate(node_->constant_properties()));
2771 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2764 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2772 __ mov(ebx, Operand(eax)); 2765 __ mov(ebx, Operand(eax));
2773 } 2766 }
2774 2767
2775 2768
2776 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2769 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2777 frame_->SpillAll(); 2770 VirtualFrame::SpilledScope spilled_scope(this);
2778 Comment cmnt(masm_, "[ ObjectLiteral"); 2771 Comment cmnt(masm_, "[ ObjectLiteral");
2779 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2772 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2780 2773
2781 // Retrieve the literal array and check the allocated entry. 2774 // Retrieve the literal array and check the allocated entry.
2782 2775
2783 // Load the function of this activation. 2776 // Load the function of this activation.
2784 __ mov(ecx, frame_->Function()); 2777 __ mov(ecx, frame_->Function());
2785 2778
2786 // Load the literals array of the function. 2779 // Load the literals array of the function.
2787 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2780 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 20 matching lines...) Expand all
2808 for (int i = 0; i < node->properties()->length(); i++) { 2801 for (int i = 0; i < node->properties()->length(); i++) {
2809 ObjectLiteral::Property* property = node->properties()->at(i); 2802 ObjectLiteral::Property* property = node->properties()->at(i);
2810 switch (property->kind()) { 2803 switch (property->kind()) {
2811 case ObjectLiteral::Property::CONSTANT: break; 2804 case ObjectLiteral::Property::CONSTANT: break;
2812 case ObjectLiteral::Property::COMPUTED: { 2805 case ObjectLiteral::Property::COMPUTED: {
2813 Handle<Object> key(property->key()->handle()); 2806 Handle<Object> key(property->key()->handle());
2814 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2807 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2815 if (key->IsSymbol()) { 2808 if (key->IsSymbol()) {
2816 __ mov(eax, frame_->Top()); 2809 __ mov(eax, frame_->Top());
2817 frame_->EmitPush(eax); 2810 frame_->EmitPush(eax);
2818 Load(property->value()); 2811 LoadAndSpill(property->value());
2819 frame_->SpillAll();
2820 frame_->EmitPop(eax); 2812 frame_->EmitPop(eax);
2821 __ Set(ecx, Immediate(key)); 2813 __ Set(ecx, Immediate(key));
2822 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 2814 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
2823 frame_->Drop(); 2815 frame_->Drop();
2824 // Ignore result. 2816 // Ignore result.
2825 break; 2817 break;
2826 } 2818 }
2827 // Fall through 2819 // Fall through
2828 } 2820 }
2829 case ObjectLiteral::Property::PROTOTYPE: { 2821 case ObjectLiteral::Property::PROTOTYPE: {
2830 __ mov(eax, frame_->Top()); 2822 __ mov(eax, frame_->Top());
2831 frame_->EmitPush(eax); 2823 frame_->EmitPush(eax);
2832 Load(property->key()); 2824 LoadAndSpill(property->key());
2833 frame_->SpillAll(); 2825 LoadAndSpill(property->value());
2834 Load(property->value());
2835 frame_->SpillAll();
2836 frame_->CallRuntime(Runtime::kSetProperty, 3); 2826 frame_->CallRuntime(Runtime::kSetProperty, 3);
2837 // Ignore result. 2827 // Ignore result.
2838 break; 2828 break;
2839 } 2829 }
2840 case ObjectLiteral::Property::SETTER: { 2830 case ObjectLiteral::Property::SETTER: {
2841 // Duplicate the resulting object on the stack. The runtime 2831 // Duplicate the resulting object on the stack. The runtime
2842 // function will pop the three arguments passed in. 2832 // function will pop the three arguments passed in.
2843 __ mov(eax, frame_->Top()); 2833 __ mov(eax, frame_->Top());
2844 frame_->EmitPush(eax); 2834 frame_->EmitPush(eax);
2845 Load(property->key()); 2835 LoadAndSpill(property->key());
2846 frame_->SpillAll();
2847 frame_->EmitPush(Immediate(Smi::FromInt(1))); 2836 frame_->EmitPush(Immediate(Smi::FromInt(1)));
2848 Load(property->value()); 2837 LoadAndSpill(property->value());
2849 frame_->SpillAll();
2850 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2838 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2851 // Ignore result. 2839 // Ignore result.
2852 break; 2840 break;
2853 } 2841 }
2854 case ObjectLiteral::Property::GETTER: { 2842 case ObjectLiteral::Property::GETTER: {
2855 // Duplicate the resulting object on the stack. The runtime 2843 // Duplicate the resulting object on the stack. The runtime
2856 // function will pop the three arguments passed in. 2844 // function will pop the three arguments passed in.
2857 __ mov(eax, frame_->Top()); 2845 __ mov(eax, frame_->Top());
2858 frame_->EmitPush(eax); 2846 frame_->EmitPush(eax);
2859 Load(property->key()); 2847 LoadAndSpill(property->key());
2860 frame_->SpillAll();
2861 frame_->EmitPush(Immediate(Smi::FromInt(0))); 2848 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2862 Load(property->value()); 2849 LoadAndSpill(property->value());
2863 frame_->SpillAll();
2864 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2850 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2865 // Ignore result. 2851 // Ignore result.
2866 break; 2852 break;
2867 } 2853 }
2868 default: UNREACHABLE(); 2854 default: UNREACHABLE();
2869 } 2855 }
2870 } 2856 }
2871 } 2857 }
2872 2858
2873 2859
2874 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2860 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2875 frame_->SpillAll(); 2861 VirtualFrame::SpilledScope spilled_scope(this);
2876 Comment cmnt(masm_, "[ ArrayLiteral"); 2862 Comment cmnt(masm_, "[ ArrayLiteral");
2877 2863
2878 // Call runtime to create the array literal. 2864 // Call runtime to create the array literal.
2879 frame_->EmitPush(Immediate(node->literals())); 2865 frame_->EmitPush(Immediate(node->literals()));
2880 // Load the function of this frame. 2866 // Load the function of this frame.
2881 __ mov(ecx, frame_->Function()); 2867 __ mov(ecx, frame_->Function());
2882 // Load the literals array of the function. 2868 // Load the literals array of the function.
2883 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2869 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2884 frame_->EmitPush(ecx); 2870 frame_->EmitPush(ecx);
2885 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2); 2871 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
2886 2872
2887 // Push the resulting array literal on the stack. 2873 // Push the resulting array literal on the stack.
2888 frame_->EmitPush(eax); 2874 frame_->EmitPush(eax);
2889 2875
2890 // Generate code to set the elements in the array that are not 2876 // Generate code to set the elements in the array that are not
2891 // literals. 2877 // literals.
2892 for (int i = 0; i < node->values()->length(); i++) { 2878 for (int i = 0; i < node->values()->length(); i++) {
2893 Expression* value = node->values()->at(i); 2879 Expression* value = node->values()->at(i);
2894 2880
2895 // If value is literal the property value is already 2881 // If value is literal the property value is already
2896 // set in the boilerplate object. 2882 // set in the boilerplate object.
2897 if (value->AsLiteral() == NULL) { 2883 if (value->AsLiteral() == NULL) {
2898 // The property must be set by generated code. 2884 // The property must be set by generated code.
2899 Load(value); 2885 LoadAndSpill(value);
2900 frame_->SpillAll();
2901 2886
2902 // Get the value off the stack. 2887 // Get the value off the stack.
2903 frame_->EmitPop(eax); 2888 frame_->EmitPop(eax);
2904 // Fetch the object literal while leaving on the stack. 2889 // Fetch the object literal while leaving on the stack.
2905 __ mov(ecx, frame_->Top()); 2890 __ mov(ecx, frame_->Top());
2906 // Get the elements array. 2891 // Get the elements array.
2907 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 2892 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2908 2893
2909 // Write to the indexed properties array. 2894 // Write to the indexed properties array.
2910 int offset = i * kPointerSize + Array::kHeaderSize; 2895 int offset = i * kPointerSize + Array::kHeaderSize;
(...skipping 24 matching lines...) Expand all
2935 frame_->EmitPush(Immediate(Smi::FromInt(0))); 2920 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2936 return; 2921 return;
2937 } 2922 }
2938 2923
2939 if (node->op() == Token::ASSIGN || 2924 if (node->op() == Token::ASSIGN ||
2940 node->op() == Token::INIT_VAR || 2925 node->op() == Token::INIT_VAR ||
2941 node->op() == Token::INIT_CONST) { 2926 node->op() == Token::INIT_CONST) {
2942 Load(node->value()); 2927 Load(node->value());
2943 2928
2944 } else { 2929 } else {
2945 frame_->SpillAll(); 2930 VirtualFrame::SpilledScope spilled_scope(this);
2946 target.GetValue(NOT_INSIDE_TYPEOF); 2931 target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
2947 frame_->SpillAll();
2948 Literal* literal = node->value()->AsLiteral(); 2932 Literal* literal = node->value()->AsLiteral();
2949 if (IsInlineSmi(literal)) { 2933 if (IsInlineSmi(literal)) {
2950 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, 2934 SmiOperation(node->binary_op(), node->type(), literal->handle(), false,
2951 NO_OVERWRITE); 2935 NO_OVERWRITE);
2952 } else { 2936 } else {
2953 Load(node->value()); 2937 LoadAndSpill(node->value());
2954 frame_->SpillAll();
2955 GenericBinaryOperation(node->binary_op(), node->type()); 2938 GenericBinaryOperation(node->binary_op(), node->type());
2956 } 2939 }
2957 } 2940 }
2958 2941
2959 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2942 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2960 if (var != NULL && 2943 if (var != NULL &&
2961 var->mode() == Variable::CONST && 2944 var->mode() == Variable::CONST &&
2962 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2945 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2963 // Assignment ignored - leave the value on the stack. 2946 // Assignment ignored - leave the value on the stack.
2964 } else { 2947 } else {
2965 __ RecordPosition(node->position()); 2948 __ RecordPosition(node->position());
2966 if (node->op() == Token::INIT_CONST) { 2949 if (node->op() == Token::INIT_CONST) {
2967 // Dynamic constant initializations must use the function context 2950 // Dynamic constant initializations must use the function context
2968 // and initialize the actual constant declared. Dynamic variable 2951 // and initialize the actual constant declared. Dynamic variable
2969 // initializations are simply assignments and use SetValue. 2952 // initializations are simply assignments and use SetValue.
2970 target.SetValue(CONST_INIT); 2953 target.SetValue(CONST_INIT);
2971 } else { 2954 } else {
2972 target.SetValue(NOT_CONST_INIT); 2955 target.SetValue(NOT_CONST_INIT);
2973 } 2956 }
2974 } 2957 }
2975 } 2958 }
2976 } 2959 }
2977 2960
2978 2961
2979 void CodeGenerator::VisitThrow(Throw* node) { 2962 void CodeGenerator::VisitThrow(Throw* node) {
2980 frame_->SpillAll(); 2963 VirtualFrame::SpilledScope spilled_scope(this);
2981 Comment cmnt(masm_, "[ Throw"); 2964 Comment cmnt(masm_, "[ Throw");
2982 2965
2983 Load(node->exception()); 2966 LoadAndSpill(node->exception());
2984 frame_->SpillAll();
2985 __ RecordPosition(node->position()); 2967 __ RecordPosition(node->position());
2986 frame_->CallRuntime(Runtime::kThrow, 1); 2968 frame_->CallRuntime(Runtime::kThrow, 1);
2987 frame_->EmitPush(eax); 2969 frame_->EmitPush(eax);
2988 } 2970 }
2989 2971
2990 2972
2991 void CodeGenerator::VisitProperty(Property* node) { 2973 void CodeGenerator::VisitProperty(Property* node) {
2992 frame_->SpillAll(); 2974 VirtualFrame::SpilledScope spilled_scope(this);
2993 Comment cmnt(masm_, "[ Property"); 2975 Comment cmnt(masm_, "[ Property");
2994 Reference property(this, node); 2976 Reference property(this, node);
2995 property.GetValue(typeof_state()); 2977 property.GetValueAndSpill(typeof_state());
2996 } 2978 }
2997 2979
2998 2980
2999 void CodeGenerator::VisitCall(Call* node) { 2981 void CodeGenerator::VisitCall(Call* node) {
3000 frame_->SpillAll(); 2982 VirtualFrame::SpilledScope spilled_scope(this);
3001 Comment cmnt(masm_, "[ Call"); 2983 Comment cmnt(masm_, "[ Call");
3002 2984
3003 ZoneList<Expression*>* args = node->arguments(); 2985 ZoneList<Expression*>* args = node->arguments();
3004 2986
3005 RecordStatementPosition(node); 2987 RecordStatementPosition(node);
3006 2988
3007 // Check if the function is a variable or a property. 2989 // Check if the function is a variable or a property.
3008 Expression* function = node->expression(); 2990 Expression* function = node->expression();
3009 Variable* var = function->AsVariableProxy()->AsVariable(); 2991 Variable* var = function->AsVariableProxy()->AsVariable();
3010 Property* property = function->AsProperty(); 2992 Property* property = function->AsProperty();
(...skipping 15 matching lines...) Expand all
3026 // Push the name of the function and the receiver onto the stack. 3008 // Push the name of the function and the receiver onto the stack.
3027 frame_->EmitPush(Immediate(var->name())); 3009 frame_->EmitPush(Immediate(var->name()));
3028 3010
3029 // Pass the global object as the receiver and let the IC stub 3011 // Pass the global object as the receiver and let the IC stub
3030 // patch the stack to use the global proxy as 'this' in the 3012 // patch the stack to use the global proxy as 'this' in the
3031 // invoked function. 3013 // invoked function.
3032 LoadGlobal(); 3014 LoadGlobal();
3033 // Load the arguments. 3015 // Load the arguments.
3034 int arg_count = args->length(); 3016 int arg_count = args->length();
3035 for (int i = 0; i < arg_count; i++) { 3017 for (int i = 0; i < arg_count; i++) {
3036 Load(args->at(i)); 3018 LoadAndSpill(args->at(i));
3037 frame_->SpillAll();
3038 } 3019 }
3039 3020
3040 // Setup the receiver register and call the IC initialization code. 3021 // Setup the receiver register and call the IC initialization code.
3041 Handle<Code> stub = (loop_nesting() > 0) 3022 Handle<Code> stub = (loop_nesting() > 0)
3042 ? ComputeCallInitializeInLoop(arg_count) 3023 ? ComputeCallInitializeInLoop(arg_count)
3043 : ComputeCallInitialize(arg_count); 3024 : ComputeCallInitialize(arg_count);
3044 __ RecordPosition(node->position()); 3025 __ RecordPosition(node->position());
3045 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 3026 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
3046 arg_count + 1); 3027 arg_count + 1);
3047 __ mov(esi, frame_->Context()); 3028 __ mov(esi, frame_->Context());
(...skipping 24 matching lines...) Expand all
3072 // Check if the key is a literal string. 3053 // Check if the key is a literal string.
3073 Literal* literal = property->key()->AsLiteral(); 3054 Literal* literal = property->key()->AsLiteral();
3074 3055
3075 if (literal != NULL && literal->handle()->IsSymbol()) { 3056 if (literal != NULL && literal->handle()->IsSymbol()) {
3076 // ------------------------------------------------------------------ 3057 // ------------------------------------------------------------------
3077 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 3058 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
3078 // ------------------------------------------------------------------ 3059 // ------------------------------------------------------------------
3079 3060
3080 // Push the name of the function and the receiver onto the stack. 3061 // Push the name of the function and the receiver onto the stack.
3081 frame_->EmitPush(Immediate(literal->handle())); 3062 frame_->EmitPush(Immediate(literal->handle()));
3082 Load(property->obj()); 3063 LoadAndSpill(property->obj());
3083 frame_->SpillAll();
3084 3064
3085 // Load the arguments. 3065 // Load the arguments.
3086 int arg_count = args->length(); 3066 int arg_count = args->length();
3087 for (int i = 0; i < arg_count; i++) { 3067 for (int i = 0; i < arg_count; i++) {
3088 Load(args->at(i)); 3068 LoadAndSpill(args->at(i));
3089 frame_->SpillAll();
3090 } 3069 }
3091 3070
3092 // Call the IC initialization code. 3071 // Call the IC initialization code.
3093 Handle<Code> stub = (loop_nesting() > 0) 3072 Handle<Code> stub = (loop_nesting() > 0)
3094 ? ComputeCallInitializeInLoop(arg_count) 3073 ? ComputeCallInitializeInLoop(arg_count)
3095 : ComputeCallInitialize(arg_count); 3074 : ComputeCallInitialize(arg_count);
3096 __ RecordPosition(node->position()); 3075 __ RecordPosition(node->position());
3097 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3076 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3098 __ mov(esi, frame_->Context()); 3077 __ mov(esi, frame_->Context());
3099 3078
3100 // Overwrite the function on the stack with the result. 3079 // Overwrite the function on the stack with the result.
3101 __ mov(frame_->Top(), eax); 3080 __ mov(frame_->Top(), eax);
3102 3081
3103 } else { 3082 } else {
3104 // ------------------------------------------- 3083 // -------------------------------------------
3105 // JavaScript example: 'array[index](1, 2, 3)' 3084 // JavaScript example: 'array[index](1, 2, 3)'
3106 // ------------------------------------------- 3085 // -------------------------------------------
3107 3086
3108 // Load the function to call from the property through a reference. 3087 // Load the function to call from the property through a reference.
3109 Reference ref(this, property); 3088 Reference ref(this, property);
3110 ref.GetValue(NOT_INSIDE_TYPEOF); 3089 ref.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3111 frame_->SpillAll();
3112 3090
3113 // Pass receiver to called function. 3091 // Pass receiver to called function.
3114 // The reference's size is non-negative. 3092 // The reference's size is non-negative.
3115 frame_->EmitPush(frame_->ElementAt(ref.size())); 3093 frame_->EmitPush(frame_->ElementAt(ref.size()));
3116 3094
3117 // Call the function. 3095 // Call the function.
3118 CallWithArguments(args, node->position()); 3096 CallWithArguments(args, node->position());
3119 } 3097 }
3120 3098
3121 } else { 3099 } else {
3122 // ---------------------------------- 3100 // ----------------------------------
3123 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 3101 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
3124 // ---------------------------------- 3102 // ----------------------------------
3125 3103
3126 // Load the function. 3104 // Load the function.
3127 Load(function); 3105 LoadAndSpill(function);
3128 frame_->SpillAll();
3129 3106
3130 // Pass the global proxy as the receiver. 3107 // Pass the global proxy as the receiver.
3131 LoadGlobalReceiver(eax); 3108 LoadGlobalReceiver(eax);
3132 3109
3133 // Call the function. 3110 // Call the function.
3134 CallWithArguments(args, node->position()); 3111 CallWithArguments(args, node->position());
3135 } 3112 }
3136 } 3113 }
3137 3114
3138 3115
3139 void CodeGenerator::VisitCallNew(CallNew* node) { 3116 void CodeGenerator::VisitCallNew(CallNew* node) {
3140 frame_->SpillAll(); 3117 VirtualFrame::SpilledScope spilled_scope(this);
3141 Comment cmnt(masm_, "[ CallNew"); 3118 Comment cmnt(masm_, "[ CallNew");
3142 3119
3143 // According to ECMA-262, section 11.2.2, page 44, the function 3120 // According to ECMA-262, section 11.2.2, page 44, the function
3144 // expression in new calls must be evaluated before the 3121 // expression in new calls must be evaluated before the
3145 // arguments. This is different from ordinary calls, where the 3122 // arguments. This is different from ordinary calls, where the
3146 // actual function to call is resolved after the arguments have been 3123 // actual function to call is resolved after the arguments have been
3147 // evaluated. 3124 // evaluated.
3148 3125
3149 // Compute function to call and use the global object as the 3126 // Compute function to call and use the global object as the
3150 // receiver. There is no need to use the global proxy here because 3127 // receiver. There is no need to use the global proxy here because
3151 // it will always be replaced with a newly allocated object. 3128 // it will always be replaced with a newly allocated object.
3152 Load(node->expression()); 3129 LoadAndSpill(node->expression());
3153 frame_->SpillAll();
3154 LoadGlobal(); 3130 LoadGlobal();
3155 3131
3156 // Push the arguments ("left-to-right") on the stack. 3132 // Push the arguments ("left-to-right") on the stack.
3157 ZoneList<Expression*>* args = node->arguments(); 3133 ZoneList<Expression*>* args = node->arguments();
3158 int arg_count = args->length(); 3134 int arg_count = args->length();
3159 for (int i = 0; i < arg_count; i++) { 3135 for (int i = 0; i < arg_count; i++) {
3160 Load(args->at(i)); 3136 LoadAndSpill(args->at(i));
3161 frame_->SpillAll();
3162 } 3137 }
3163 3138
3164 // Constructors are called with the number of arguments in register 3139 // Constructors are called with the number of arguments in register
3165 // eax for now. Another option would be to have separate construct 3140 // eax for now. Another option would be to have separate construct
3166 // call trampolines per different arguments counts encountered. 3141 // call trampolines per different arguments counts encountered.
3167 __ Set(eax, Immediate(arg_count)); 3142 __ Set(eax, Immediate(arg_count));
3168 3143
3169 // Load the function into temporary function slot as per calling 3144 // Load the function into temporary function slot as per calling
3170 // convention. 3145 // convention.
3171 __ mov(edi, frame_->ElementAt(arg_count + 1)); 3146 __ mov(edi, frame_->ElementAt(arg_count + 1));
3172 3147
3173 // Call the construct call builtin that handles allocation and 3148 // Call the construct call builtin that handles allocation and
3174 // constructor invocation. 3149 // constructor invocation.
3175 __ RecordPosition(node->position()); 3150 __ RecordPosition(node->position());
3176 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 3151 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
3177 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 3152 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
3178 // Discard the function and "push" the newly created object. 3153 // Discard the function and "push" the newly created object.
3179 __ mov(frame_->Top(), eax); 3154 __ mov(frame_->Top(), eax);
3180 } 3155 }
3181 3156
3182 3157
3183 void CodeGenerator::VisitCallEval(CallEval* node) { 3158 void CodeGenerator::VisitCallEval(CallEval* node) {
3184 frame_->SpillAll(); 3159 VirtualFrame::SpilledScope spilled_scope(this);
3185 Comment cmnt(masm_, "[ CallEval"); 3160 Comment cmnt(masm_, "[ CallEval");
3186 3161
3187 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve 3162 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
3188 // the function we need to call and the receiver of the call. 3163 // the function we need to call and the receiver of the call.
3189 // Then we call the resolved function using the given arguments. 3164 // Then we call the resolved function using the given arguments.
3190 3165
3191 ZoneList<Expression*>* args = node->arguments(); 3166 ZoneList<Expression*>* args = node->arguments();
3192 Expression* function = node->expression(); 3167 Expression* function = node->expression();
3193 3168
3194 RecordStatementPosition(node); 3169 RecordStatementPosition(node);
3195 3170
3196 // Prepare stack for call to resolved function. 3171 // Prepare stack for call to resolved function.
3197 Load(function); 3172 LoadAndSpill(function);
3198 frame_->SpillAll();
3199 // Allocate a frame slot for the receiver. 3173 // Allocate a frame slot for the receiver.
3200 frame_->EmitPush(Immediate(Factory::undefined_value())); 3174 frame_->EmitPush(Immediate(Factory::undefined_value()));
3201 int arg_count = args->length(); 3175 int arg_count = args->length();
3202 for (int i = 0; i < arg_count; i++) { 3176 for (int i = 0; i < arg_count; i++) {
3203 Load(args->at(i)); 3177 LoadAndSpill(args->at(i));
3204 frame_->SpillAll();
3205 } 3178 }
3206 3179
3207 // Prepare stack for call to ResolvePossiblyDirectEval. 3180 // Prepare stack for call to ResolvePossiblyDirectEval.
3208 frame_->EmitPush(frame_->ElementAt(arg_count + 1)); 3181 frame_->EmitPush(frame_->ElementAt(arg_count + 1));
3209 if (arg_count > 0) { 3182 if (arg_count > 0) {
3210 frame_->EmitPush(frame_->ElementAt(arg_count)); 3183 frame_->EmitPush(frame_->ElementAt(arg_count));
3211 } else { 3184 } else {
3212 frame_->EmitPush(Immediate(Factory::undefined_value())); 3185 frame_->EmitPush(Immediate(Factory::undefined_value()));
3213 } 3186 }
3214 3187
(...skipping 13 matching lines...) Expand all
3228 frame_->CallStub(&call_function, arg_count + 1); 3201 frame_->CallStub(&call_function, arg_count + 1);
3229 3202
3230 // Restore context and pop function from the stack. 3203 // Restore context and pop function from the stack.
3231 __ mov(esi, frame_->Context()); 3204 __ mov(esi, frame_->Context());
3232 __ mov(frame_->Top(), eax); 3205 __ mov(frame_->Top(), eax);
3233 } 3206 }
3234 3207
3235 3208
3236 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3209 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3237 ASSERT(args->length() == 1); 3210 ASSERT(args->length() == 1);
3238 Load(args->at(0)); 3211 LoadAndSpill(args->at(0));
3239 frame_->SpillAll();
3240 frame_->EmitPop(eax); 3212 frame_->EmitPop(eax);
3241 __ test(eax, Immediate(kSmiTagMask)); 3213 __ test(eax, Immediate(kSmiTagMask));
3242 cc_reg_ = zero; 3214 cc_reg_ = zero;
3243 } 3215 }
3244 3216
3245 3217
3246 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3218 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3247 ASSERT(args->length() == 1); 3219 ASSERT(args->length() == 1);
3248 Load(args->at(0)); 3220 LoadAndSpill(args->at(0));
3249 frame_->SpillAll();
3250 frame_->EmitPop(eax); 3221 frame_->EmitPop(eax);
3251 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 3222 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
3252 cc_reg_ = zero; 3223 cc_reg_ = zero;
3253 } 3224 }
3254 3225
3255 3226
3256 // This generates code that performs a charCodeAt() call or returns 3227 // This generates code that performs a charCodeAt() call or returns
3257 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3228 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3258 // It can handle flat and sliced strings, 8 and 16 bit characters and 3229 // It can handle flat and sliced strings, 8 and 16 bit characters and
3259 // cons strings where the answer is found in the left hand branch of the 3230 // cons strings where the answer is found in the left hand branch of the
3260 // cons. The slow case will flatten the string, which will ensure that 3231 // cons. The slow case will flatten the string, which will ensure that
3261 // the answer is in the left hand side the next time around. 3232 // the answer is in the left hand side the next time around.
3262 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3233 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3263 ASSERT(args->length() == 2); 3234 ASSERT(args->length() == 2);
3264 3235
3265 JumpTarget slow_case(this); 3236 JumpTarget slow_case(this);
3266 JumpTarget end(this); 3237 JumpTarget end(this);
3267 JumpTarget not_a_flat_string(this); 3238 JumpTarget not_a_flat_string(this);
3268 JumpTarget not_a_cons_string_either(this); 3239 JumpTarget not_a_cons_string_either(this);
3269 JumpTarget try_again_with_new_string(this); 3240 JumpTarget try_again_with_new_string(this);
3270 JumpTarget ascii_string(this); 3241 JumpTarget ascii_string(this);
3271 JumpTarget got_char_code(this); 3242 JumpTarget got_char_code(this);
3272 3243
3273 // Load the string into eax and the index into ebx. 3244 // Load the string into eax and the index into ebx.
3274 Load(args->at(0)); 3245 LoadAndSpill(args->at(0));
3275 frame_->SpillAll(); 3246 LoadAndSpill(args->at(1));
3276 Load(args->at(1));
3277 frame_->SpillAll();
3278 frame_->EmitPop(ebx); 3247 frame_->EmitPop(ebx);
3279 frame_->EmitPop(eax); 3248 frame_->EmitPop(eax);
3280 // If the receiver is a smi return undefined. 3249 // If the receiver is a smi return undefined.
3281 ASSERT(kSmiTag == 0); 3250 ASSERT(kSmiTag == 0);
3282 __ test(eax, Immediate(kSmiTagMask)); 3251 __ test(eax, Immediate(kSmiTagMask));
3283 slow_case.Branch(zero, not_taken); 3252 slow_case.Branch(zero, not_taken);
3284 3253
3285 // Check for negative or non-smi index. 3254 // Check for negative or non-smi index.
3286 ASSERT(kSmiTag == 0); 3255 ASSERT(kSmiTag == 0);
3287 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 3256 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3367 3336
3368 slow_case.Bind(); 3337 slow_case.Bind();
3369 frame_->EmitPush(Immediate(Factory::undefined_value())); 3338 frame_->EmitPush(Immediate(Factory::undefined_value()));
3370 3339
3371 end.Bind(); 3340 end.Bind();
3372 } 3341 }
3373 3342
3374 3343
3375 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3344 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3376 ASSERT(args->length() == 1); 3345 ASSERT(args->length() == 1);
3377 Load(args->at(0)); 3346 LoadAndSpill(args->at(0));
3378 frame_->SpillAll();
3379 JumpTarget answer(this); 3347 JumpTarget answer(this);
3380 // We need the CC bits to come out as not_equal in the case where the 3348 // We need the CC bits to come out as not_equal in the case where the
3381 // object is a smi. This can't be done with the usual test opcode so 3349 // object is a smi. This can't be done with the usual test opcode so
3382 // we copy the object to ecx and do some destructive ops on it that 3350 // we copy the object to ecx and do some destructive ops on it that
3383 // result in the right CC bits. 3351 // result in the right CC bits.
3384 frame_->EmitPop(eax); 3352 frame_->EmitPop(eax);
3385 __ mov(ecx, Operand(eax)); 3353 __ mov(ecx, Operand(eax));
3386 __ and_(ecx, kSmiTagMask); 3354 __ and_(ecx, kSmiTagMask);
3387 __ xor_(ecx, kSmiTagMask); 3355 __ xor_(ecx, kSmiTagMask);
3388 answer.Branch(not_equal, not_taken); 3356 answer.Branch(not_equal, not_taken);
(...skipping 18 matching lines...) Expand all
3407 // Call the shared stub to get to the arguments.length. 3375 // Call the shared stub to get to the arguments.length.
3408 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 3376 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3409 frame_->CallStub(&stub, 0); 3377 frame_->CallStub(&stub, 0);
3410 frame_->EmitPush(eax); 3378 frame_->EmitPush(eax);
3411 } 3379 }
3412 3380
3413 3381
3414 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3382 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3415 ASSERT(args->length() == 1); 3383 ASSERT(args->length() == 1);
3416 JumpTarget leave(this); 3384 JumpTarget leave(this);
3417 Load(args->at(0)); // Load the object. 3385 LoadAndSpill(args->at(0)); // Load the object.
3418 frame_->SpillAll();
3419 __ mov(eax, frame_->Top()); 3386 __ mov(eax, frame_->Top());
3420 // if (object->IsSmi()) return object. 3387 // if (object->IsSmi()) return object.
3421 __ test(eax, Immediate(kSmiTagMask)); 3388 __ test(eax, Immediate(kSmiTagMask));
3422 leave.Branch(zero, taken); 3389 leave.Branch(zero, taken);
3423 // It is a heap object - get map. 3390 // It is a heap object - get map.
3424 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 3391 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3425 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 3392 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3426 // if (!object->IsJSValue()) return object. 3393 // if (!object->IsJSValue()) return object.
3427 __ cmp(ecx, JS_VALUE_TYPE); 3394 __ cmp(ecx, JS_VALUE_TYPE);
3428 leave.Branch(not_equal, not_taken); 3395 leave.Branch(not_equal, not_taken);
3429 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 3396 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
3430 __ mov(frame_->Top(), eax); 3397 __ mov(frame_->Top(), eax);
3431 leave.Bind(); 3398 leave.Bind();
3432 } 3399 }
3433 3400
3434 3401
3435 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3402 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3436 ASSERT(args->length() == 2); 3403 ASSERT(args->length() == 2);
3437 JumpTarget leave(this); 3404 JumpTarget leave(this);
3438 Load(args->at(0)); // Load the object. 3405 LoadAndSpill(args->at(0)); // Load the object.
3439 frame_->SpillAll(); 3406 LoadAndSpill(args->at(1)); // Load the value.
3440 Load(args->at(1)); // Load the value.
3441 frame_->SpillAll();
3442 __ mov(eax, frame_->ElementAt(1)); 3407 __ mov(eax, frame_->ElementAt(1));
3443 __ mov(ecx, frame_->Top()); 3408 __ mov(ecx, frame_->Top());
3444 // if (object->IsSmi()) return object. 3409 // if (object->IsSmi()) return object.
3445 __ test(eax, Immediate(kSmiTagMask)); 3410 __ test(eax, Immediate(kSmiTagMask));
3446 leave.Branch(zero, taken); 3411 leave.Branch(zero, taken);
3447 // It is a heap object - get map. 3412 // It is a heap object - get map.
3448 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 3413 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3449 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 3414 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
3450 // if (!object->IsJSValue()) return object. 3415 // if (!object->IsJSValue()) return object.
3451 __ cmp(ebx, JS_VALUE_TYPE); 3416 __ cmp(ebx, JS_VALUE_TYPE);
3452 leave.Branch(not_equal, not_taken); 3417 leave.Branch(not_equal, not_taken);
3453 // Store the value. 3418 // Store the value.
3454 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); 3419 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx);
3455 // Update the write barrier. 3420 // Update the write barrier.
3456 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); 3421 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx);
3457 // Leave. 3422 // Leave.
3458 leave.Bind(); 3423 leave.Bind();
3459 __ mov(ecx, frame_->Top()); 3424 __ mov(ecx, frame_->Top());
3460 frame_->Drop(); 3425 frame_->Drop();
3461 __ mov(frame_->Top(), ecx); 3426 __ mov(frame_->Top(), ecx);
3462 } 3427 }
3463 3428
3464 3429
3465 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 3430 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
3466 ASSERT(args->length() == 1); 3431 ASSERT(args->length() == 1);
3467 3432
3468 // Load the key onto the stack and set register eax to the formal 3433 // Load the key onto the stack and set register eax to the formal
3469 // parameters count for the currently executing function. 3434 // parameters count for the currently executing function.
3470 Load(args->at(0)); 3435 LoadAndSpill(args->at(0));
3471 frame_->SpillAll();
3472 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3436 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3473 3437
3474 // Call the shared stub to get to arguments[key]. 3438 // Call the shared stub to get to arguments[key].
3475 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 3439 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3476 frame_->CallStub(&stub, 0); 3440 frame_->CallStub(&stub, 0);
3477 __ mov(frame_->Top(), eax); 3441 __ mov(frame_->Top(), eax);
3478 } 3442 }
3479 3443
3480 3444
3481 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3445 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3482 ASSERT(args->length() == 2); 3446 ASSERT(args->length() == 2);
3483 3447
3484 // Load the two objects into registers and perform the comparison. 3448 // Load the two objects into registers and perform the comparison.
3485 Load(args->at(0)); 3449 LoadAndSpill(args->at(0));
3486 frame_->SpillAll(); 3450 LoadAndSpill(args->at(1));
3487 Load(args->at(1));
3488 frame_->SpillAll();
3489 frame_->EmitPop(eax); 3451 frame_->EmitPop(eax);
3490 frame_->EmitPop(ecx); 3452 frame_->EmitPop(ecx);
3491 __ cmp(eax, Operand(ecx)); 3453 __ cmp(eax, Operand(ecx));
3492 cc_reg_ = equal; 3454 cc_reg_ = equal;
3493 } 3455 }
3494 3456
3495 3457
3496 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 3458 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3497 frame_->SpillAll(); 3459 VirtualFrame::SpilledScope spilled_scope(this);
3498 if (CheckForInlineRuntimeCall(node)) { 3460 if (CheckForInlineRuntimeCall(node)) {
3499 return; 3461 return;
3500 } 3462 }
3501 3463
3502 ZoneList<Expression*>* args = node->arguments(); 3464 ZoneList<Expression*>* args = node->arguments();
3503 Comment cmnt(masm_, "[ CallRuntime"); 3465 Comment cmnt(masm_, "[ CallRuntime");
3504 Runtime::Function* function = node->function(); 3466 Runtime::Function* function = node->function();
3505 3467
3506 if (function == NULL) { 3468 if (function == NULL) {
3507 // Prepare stack for calling JS runtime function. 3469 // Prepare stack for calling JS runtime function.
3508 frame_->EmitPush(Immediate(node->name())); 3470 frame_->EmitPush(Immediate(node->name()));
3509 // Push the builtins object found in the current global object. 3471 // Push the builtins object found in the current global object.
3510 __ mov(edx, GlobalObject()); 3472 __ mov(edx, GlobalObject());
3511 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 3473 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset));
3512 } 3474 }
3513 3475
3514 // Push the arguments ("left-to-right"). 3476 // Push the arguments ("left-to-right").
3515 int arg_count = args->length(); 3477 int arg_count = args->length();
3516 for (int i = 0; i < arg_count; i++) { 3478 for (int i = 0; i < arg_count; i++) {
3517 Load(args->at(i)); 3479 LoadAndSpill(args->at(i));
3518 frame_->SpillAll();
3519 } 3480 }
3520 3481
3521 if (function == NULL) { 3482 if (function == NULL) {
3522 // Call the JS runtime function. 3483 // Call the JS runtime function.
3523 Handle<Code> stub = ComputeCallInitialize(arg_count); 3484 Handle<Code> stub = ComputeCallInitialize(arg_count);
3524 __ Set(eax, Immediate(args->length())); 3485 __ Set(eax, Immediate(args->length()));
3525 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3486 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3526 __ mov(esi, frame_->Context()); 3487 __ mov(esi, frame_->Context());
3527 __ mov(frame_->Top(), eax); 3488 __ mov(frame_->Top(), eax);
3528 } else { 3489 } else {
3529 // Call the C runtime function. 3490 // Call the C runtime function.
3530 frame_->CallRuntime(function, arg_count); 3491 frame_->CallRuntime(function, arg_count);
3531 frame_->EmitPush(eax); 3492 frame_->EmitPush(eax);
3532 } 3493 }
3533 } 3494 }
3534 3495
3535 3496
3536 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3497 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3537 frame_->SpillAll(); 3498 VirtualFrame::SpilledScope spilled_scope(this);
3538 // Note that because of NOT and an optimization in comparison of a typeof 3499 // Note that because of NOT and an optimization in comparison of a typeof
3539 // expression to a literal string, this function can fail to leave a value 3500 // expression to a literal string, this function can fail to leave a value
3540 // on top of the frame or in the cc register. 3501 // on top of the frame or in the cc register.
3541 Comment cmnt(masm_, "[ UnaryOperation"); 3502 Comment cmnt(masm_, "[ UnaryOperation");
3542 3503
3543 Token::Value op = node->op(); 3504 Token::Value op = node->op();
3544 3505
3545 if (op == Token::NOT) { 3506 if (op == Token::NOT) {
3546 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 3507 LoadConditionAndSpill(node->expression(), NOT_INSIDE_TYPEOF,
3547 false_target(), true_target(), true); 3508 false_target(), true_target(), true);
3548 cc_reg_ = NegateCondition(cc_reg_); 3509 cc_reg_ = NegateCondition(cc_reg_);
3549 3510
3550 } else if (op == Token::DELETE) { 3511 } else if (op == Token::DELETE) {
3551 Property* property = node->expression()->AsProperty(); 3512 Property* property = node->expression()->AsProperty();
3552 if (property != NULL) { 3513 if (property != NULL) {
3553 Load(property->obj()); 3514 LoadAndSpill(property->obj());
3554 frame_->SpillAll(); 3515 LoadAndSpill(property->key());
3555 Load(property->key());
3556 frame_->SpillAll();
3557 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3516 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3558 frame_->EmitPush(eax); 3517 frame_->EmitPush(eax);
3559 return; 3518 return;
3560 } 3519 }
3561 3520
3562 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 3521 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
3563 if (variable != NULL) { 3522 if (variable != NULL) {
3564 Slot* slot = variable->slot(); 3523 Slot* slot = variable->slot();
3565 if (variable->is_global()) { 3524 if (variable->is_global()) {
3566 LoadGlobal(); 3525 LoadGlobal();
(...skipping 14 matching lines...) Expand all
3581 frame_->EmitPush(eax); 3540 frame_->EmitPush(eax);
3582 return; 3541 return;
3583 } 3542 }
3584 3543
3585 // Default: Result of deleting non-global, not dynamically 3544 // Default: Result of deleting non-global, not dynamically
3586 // introduced variables is false. 3545 // introduced variables is false.
3587 frame_->EmitPush(Immediate(Factory::false_value())); 3546 frame_->EmitPush(Immediate(Factory::false_value()));
3588 3547
3589 } else { 3548 } else {
3590 // Default: Result of deleting expressions is true. 3549 // Default: Result of deleting expressions is true.
3591 Load(node->expression()); // may have side-effects 3550 LoadAndSpill(node->expression()); // may have side-effects
3592 frame_->SpillAll();
3593 __ Set(frame_->Top(), Immediate(Factory::true_value())); 3551 __ Set(frame_->Top(), Immediate(Factory::true_value()));
3594 } 3552 }
3595 3553
3596 } else if (op == Token::TYPEOF) { 3554 } else if (op == Token::TYPEOF) {
3597 // Special case for loading the typeof expression; see comment on 3555 // Special case for loading the typeof expression; see comment on
3598 // LoadTypeofExpression(). 3556 // LoadTypeofExpression().
3599 LoadTypeofExpression(node->expression()); 3557 LoadTypeofExpression(node->expression());
3600 frame_->CallRuntime(Runtime::kTypeof, 1); 3558 frame_->CallRuntime(Runtime::kTypeof, 1);
3601 frame_->EmitPush(eax); 3559 frame_->EmitPush(eax);
3602 3560
3603 } else { 3561 } else {
3604 Load(node->expression()); 3562 LoadAndSpill(node->expression());
3605 frame_->SpillAll();
3606 switch (op) { 3563 switch (op) {
3607 case Token::NOT: 3564 case Token::NOT:
3608 case Token::DELETE: 3565 case Token::DELETE:
3609 case Token::TYPEOF: 3566 case Token::TYPEOF:
3610 UNREACHABLE(); // handled above 3567 UNREACHABLE(); // handled above
3611 break; 3568 break;
3612 3569
3613 case Token::SUB: { 3570 case Token::SUB: {
3614 UnarySubStub stub; 3571 UnarySubStub stub;
3615 // TODO(1222589): remove dependency of TOS being cached inside stub 3572 // TODO(1222589): remove dependency of TOS being cached inside stub
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
3744 if (is_postfix_) { 3701 if (is_postfix_) {
3745 RevertToNumberStub to_number_stub(is_increment_); 3702 RevertToNumberStub to_number_stub(is_increment_);
3746 __ CallStub(&to_number_stub); 3703 __ CallStub(&to_number_stub);
3747 } 3704 }
3748 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); 3705 CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
3749 __ CallStub(&stub); 3706 __ CallStub(&stub);
3750 } 3707 }
3751 3708
3752 3709
3753 void CodeGenerator::VisitCountOperation(CountOperation* node) { 3710 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3754 frame_->SpillAll(); 3711 VirtualFrame::SpilledScope spilled_scope(this);
3755 Comment cmnt(masm_, "[ CountOperation"); 3712 Comment cmnt(masm_, "[ CountOperation");
3756 3713
3757 bool is_postfix = node->is_postfix(); 3714 bool is_postfix = node->is_postfix();
3758 bool is_increment = node->op() == Token::INC; 3715 bool is_increment = node->op() == Token::INC;
3759 3716
3760 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3717 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3761 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3718 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3762 3719
3763 // Postfix: Make room for the result. 3720 // Postfix: Make room for the result.
3764 if (is_postfix) { 3721 if (is_postfix) {
3765 frame_->EmitPush(Immediate(0)); 3722 frame_->EmitPush(Immediate(0));
3766 } 3723 }
3767 3724
3768 { Reference target(this, node->expression()); 3725 { Reference target(this, node->expression());
3769 if (target.is_illegal()) { 3726 if (target.is_illegal()) {
3770 // Spoof the virtual frame to have the expected height (one higher 3727 // Spoof the virtual frame to have the expected height (one higher
3771 // than on entry). 3728 // than on entry).
3772 if (!is_postfix) { 3729 if (!is_postfix) {
3773 frame_->EmitPush(Immediate(Smi::FromInt(0))); 3730 frame_->EmitPush(Immediate(Smi::FromInt(0)));
3774 } 3731 }
3775 return; 3732 return;
3776 } 3733 }
3777 target.GetValue(NOT_INSIDE_TYPEOF); 3734 target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3778 frame_->SpillAll();
3779 3735
3780 CountOperationDeferred* deferred = 3736 CountOperationDeferred* deferred =
3781 new CountOperationDeferred(this, is_postfix, is_increment, 3737 new CountOperationDeferred(this, is_postfix, is_increment,
3782 target.size() * kPointerSize); 3738 target.size() * kPointerSize);
3783 3739
3784 frame_->EmitPop(eax); // Load TOS into eax for calculations below 3740 frame_->EmitPop(eax); // Load TOS into eax for calculations below
3785 3741
3786 // Postfix: Store the old value as the result. 3742 // Postfix: Store the old value as the result.
3787 if (is_postfix) { 3743 if (is_postfix) {
3788 __ mov(frame_->ElementAt(target.size()), eax); 3744 __ mov(frame_->ElementAt(target.size()), eax);
(...skipping 20 matching lines...) Expand all
3809 } 3765 }
3810 3766
3811 // Postfix: Discard the new value and use the old. 3767 // Postfix: Discard the new value and use the old.
3812 if (is_postfix) { 3768 if (is_postfix) {
3813 frame_->Drop(); 3769 frame_->Drop();
3814 } 3770 }
3815 } 3771 }
3816 3772
3817 3773
3818 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3774 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3819 frame_->SpillAll(); 3775 VirtualFrame::SpilledScope spilled_scope(this);
3820 // Note that due to an optimization in comparison operations (typeof 3776 // Note that due to an optimization in comparison operations (typeof
3821 // compared to a string literal), we can evaluate a binary expression such 3777 // compared to a string literal), we can evaluate a binary expression such
3822 // as AND or OR and not leave a value on the frame or in the cc register. 3778 // as AND or OR and not leave a value on the frame or in the cc register.
3823 Comment cmnt(masm_, "[ BinaryOperation"); 3779 Comment cmnt(masm_, "[ BinaryOperation");
3824 Token::Value op = node->op(); 3780 Token::Value op = node->op();
3825 3781
3826 // According to ECMA-262 section 11.11, page 58, the binary logical 3782 // According to ECMA-262 section 11.11, page 58, the binary logical
3827 // operators must yield the result of one of the two expressions 3783 // operators must yield the result of one of the two expressions
3828 // before any ToBoolean() conversions. This means that the value 3784 // before any ToBoolean() conversions. This means that the value
3829 // produced by a && or || operator is not necessarily a boolean. 3785 // produced by a && or || operator is not necessarily a boolean.
3830 3786
3831 // NOTE: If the left hand side produces a materialized value (not in 3787 // NOTE: If the left hand side produces a materialized value (not in
3832 // the CC register), we force the right hand side to do the 3788 // the CC register), we force the right hand side to do the
3833 // same. This is necessary because we may have to branch to the exit 3789 // same. This is necessary because we may have to branch to the exit
3834 // after evaluating the left hand side (due to the shortcut 3790 // after evaluating the left hand side (due to the shortcut
3835 // semantics), but the compiler must (statically) know if the result 3791 // semantics), but the compiler must (statically) know if the result
3836 // of compiling the binary operation is materialized or not. 3792 // of compiling the binary operation is materialized or not.
3837 3793
3838 if (op == Token::AND) { 3794 if (op == Token::AND) {
3839 JumpTarget is_true(this); 3795 JumpTarget is_true(this);
3840 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &is_true, 3796 LoadConditionAndSpill(node->left(), NOT_INSIDE_TYPEOF,
3841 false_target(), false); 3797 &is_true, false_target(), false);
3842 if (has_cc() || frame_ == NULL) { 3798 if (has_cc() || frame_ == NULL) {
3843 if (has_cc()) { 3799 if (has_cc()) {
3844 ASSERT(frame_ != NULL); 3800 ASSERT(frame_ != NULL);
3845 Branch(false, false_target()); 3801 Branch(false, false_target());
3846 } 3802 }
3847 3803
3848 if (frame_ != NULL || is_true.is_linked()) { 3804 if (frame_ != NULL || is_true.is_linked()) {
3849 // Evaluate right side expression. 3805 // Evaluate right side expression.
3850 is_true.Bind(); 3806 is_true.Bind();
3851 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3807 LoadConditionAndSpill(node->right(), NOT_INSIDE_TYPEOF,
3852 false_target(), false); 3808 true_target(), false_target(), false);
3853 } 3809 }
3854 } else { 3810 } else {
3855 frame_->SpillAll();
3856 // We have a materialized value on the frame. 3811 // We have a materialized value on the frame.
3857 JumpTarget pop_and_continue(this); 3812 JumpTarget pop_and_continue(this);
3858 JumpTarget exit(this); 3813 JumpTarget exit(this);
3859 3814
3860 // Avoid popping the result if it converts to 'false' using the 3815 // Avoid popping the result if it converts to 'false' using the
3861 // standard ToBoolean() conversion as described in ECMA-262, section 3816 // standard ToBoolean() conversion as described in ECMA-262, section
3862 // 9.2, page 30. 3817 // 9.2, page 30.
3863 // 3818 //
3864 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3819 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3865 __ mov(eax, frame_->Top()); 3820 __ mov(eax, frame_->Top());
3866 frame_->EmitPush(eax); 3821 frame_->EmitPush(eax);
3867 ToBoolean(&pop_and_continue, &exit); 3822 ToBoolean(&pop_and_continue, &exit);
3868 Branch(false, &exit); 3823 Branch(false, &exit);
3869 3824
3870 // Pop the result of evaluating the first part. 3825 // Pop the result of evaluating the first part.
3871 pop_and_continue.Bind(); 3826 pop_and_continue.Bind();
3872 frame_->Drop(); 3827 frame_->Drop();
3873 3828
3874 // Evaluate right side expression. 3829 // Evaluate right side expression.
3875 is_true.Bind(); 3830 is_true.Bind();
3876 Load(node->right()); 3831 LoadAndSpill(node->right());
3877 frame_->SpillAll();
3878 3832
3879 // Exit (always with a materialized value). 3833 // Exit (always with a materialized value).
3880 exit.Bind(); 3834 exit.Bind();
3881 } 3835 }
3882 3836
3883 } else if (op == Token::OR) { 3837 } else if (op == Token::OR) {
3884 JumpTarget is_false(this); 3838 JumpTarget is_false(this);
3885 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(), 3839 LoadConditionAndSpill(node->left(), NOT_INSIDE_TYPEOF,
3886 &is_false, false); 3840 true_target(), &is_false, false);
3887 if (has_cc() || frame_ == NULL) { 3841 if (has_cc() || frame_ == NULL) {
3888 if (has_cc()) { 3842 if (has_cc()) {
3889 ASSERT(frame_ != NULL); 3843 ASSERT(frame_ != NULL);
3890 Branch(true, true_target()); 3844 Branch(true, true_target());
3891 } 3845 }
3892 3846
3893 if (frame_ != NULL || is_false.is_linked()) { 3847 if (frame_ != NULL || is_false.is_linked()) {
3894 // Evaluate right side expression. 3848 // Evaluate right side expression.
3895 is_false.Bind(); 3849 is_false.Bind();
3896 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3850 LoadConditionAndSpill(node->right(), NOT_INSIDE_TYPEOF,
3897 false_target(), false); 3851 true_target(), false_target(), false);
3898 } 3852 }
3899 3853
3900 } else { 3854 } else {
3901 frame_->SpillAll();
3902 // We have a materialized value on the frame. 3855 // We have a materialized value on the frame.
3903 JumpTarget pop_and_continue(this); 3856 JumpTarget pop_and_continue(this);
3904 JumpTarget exit(this); 3857 JumpTarget exit(this);
3905 3858
3906 // Avoid popping the result if it converts to 'true' using the 3859 // Avoid popping the result if it converts to 'true' using the
3907 // standard ToBoolean() conversion as described in ECMA-262, 3860 // standard ToBoolean() conversion as described in ECMA-262,
3908 // section 9.2, page 30. 3861 // section 9.2, page 30.
3909 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3862 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3910 __ mov(eax, frame_->Top()); 3863 __ mov(eax, frame_->Top());
3911 frame_->EmitPush(eax); 3864 frame_->EmitPush(eax);
3912 ToBoolean(&exit, &pop_and_continue); 3865 ToBoolean(&exit, &pop_and_continue);
3913 Branch(true, &exit); 3866 Branch(true, &exit);
3914 3867
3915 // Pop the result of evaluating the first part. 3868 // Pop the result of evaluating the first part.
3916 pop_and_continue.Bind(); 3869 pop_and_continue.Bind();
3917 frame_->Drop(); 3870 frame_->Drop();
3918 3871
3919 // Evaluate right side expression. 3872 // Evaluate right side expression.
3920 is_false.Bind(); 3873 is_false.Bind();
3921 Load(node->right()); 3874 LoadAndSpill(node->right());
3922 frame_->SpillAll();
3923 3875
3924 // Exit (always with a materialized value). 3876 // Exit (always with a materialized value).
3925 exit.Bind(); 3877 exit.Bind();
3926 } 3878 }
3927 3879
3928 } else { 3880 } else {
3929 // NOTE: The code below assumes that the slow cases (calls to runtime) 3881 // NOTE: The code below assumes that the slow cases (calls to runtime)
3930 // never return a constant/immutable object. 3882 // never return a constant/immutable object.
3931 OverwriteMode overwrite_mode = NO_OVERWRITE; 3883 OverwriteMode overwrite_mode = NO_OVERWRITE;
3932 if (node->left()->AsBinaryOperation() != NULL && 3884 if (node->left()->AsBinaryOperation() != NULL &&
3933 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) { 3885 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
3934 overwrite_mode = OVERWRITE_LEFT; 3886 overwrite_mode = OVERWRITE_LEFT;
3935 } else if (node->right()->AsBinaryOperation() != NULL && 3887 } else if (node->right()->AsBinaryOperation() != NULL &&
3936 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) { 3888 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
3937 overwrite_mode = OVERWRITE_RIGHT; 3889 overwrite_mode = OVERWRITE_RIGHT;
3938 } 3890 }
3939 3891
3940 // Optimize for the case where (at least) one of the expressions 3892 // Optimize for the case where (at least) one of the expressions
3941 // is a literal small integer. 3893 // is a literal small integer.
3942 Literal* lliteral = node->left()->AsLiteral(); 3894 Literal* lliteral = node->left()->AsLiteral();
3943 Literal* rliteral = node->right()->AsLiteral(); 3895 Literal* rliteral = node->right()->AsLiteral();
3944 3896
3945 if (IsInlineSmi(rliteral)) { 3897 if (IsInlineSmi(rliteral)) {
3946 Load(node->left()); 3898 LoadAndSpill(node->left());
3947 frame_->SpillAll();
3948 SmiOperation(node->op(), node->type(), rliteral->handle(), false, 3899 SmiOperation(node->op(), node->type(), rliteral->handle(), false,
3949 overwrite_mode); 3900 overwrite_mode);
3950 } else if (IsInlineSmi(lliteral)) { 3901 } else if (IsInlineSmi(lliteral)) {
3951 Load(node->right()); 3902 LoadAndSpill(node->right());
3952 frame_->SpillAll();
3953 SmiOperation(node->op(), node->type(), lliteral->handle(), true, 3903 SmiOperation(node->op(), node->type(), lliteral->handle(), true,
3954 overwrite_mode); 3904 overwrite_mode);
3955 } else { 3905 } else {
3956 Load(node->left()); 3906 LoadAndSpill(node->left());
3957 frame_->SpillAll(); 3907 LoadAndSpill(node->right());
3958 Load(node->right());
3959 frame_->SpillAll();
3960 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); 3908 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3961 } 3909 }
3962 } 3910 }
3963 } 3911 }
3964 3912
3965 3913
3966 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3914 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3967 frame_->SpillAll(); 3915 VirtualFrame::SpilledScope spilled_scope(this);
3968 frame_->EmitPush(frame_->Function()); 3916 frame_->EmitPush(frame_->Function());
3969 } 3917 }
3970 3918
3971 3919
3972 class InstanceofStub: public CodeStub { 3920 class InstanceofStub: public CodeStub {
3973 public: 3921 public:
3974 InstanceofStub() { } 3922 InstanceofStub() { }
3975 3923
3976 void Generate(MacroAssembler* masm); 3924 void Generate(MacroAssembler* masm);
3977 3925
(...skipping 15 matching lines...) Expand all
3993 // literal 'null'. If so, we optimize the code by inlining a null check 3941 // literal 'null'. If so, we optimize the code by inlining a null check
3994 // instead of calling the (very) general runtime routine for checking 3942 // instead of calling the (very) general runtime routine for checking
3995 // equality. 3943 // equality.
3996 if (op == Token::EQ || op == Token::EQ_STRICT) { 3944 if (op == Token::EQ || op == Token::EQ_STRICT) {
3997 bool left_is_null = 3945 bool left_is_null =
3998 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 3946 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
3999 bool right_is_null = 3947 bool right_is_null =
4000 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 3948 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
4001 // The 'null' value can only be equal to 'null' or 'undefined'. 3949 // The 'null' value can only be equal to 'null' or 'undefined'.
4002 if (left_is_null || right_is_null) { 3950 if (left_is_null || right_is_null) {
4003 frame_->SpillAll(); 3951 VirtualFrame::SpilledScope spilled_scope(this);
4004 Load(left_is_null ? right : left); 3952 LoadAndSpill(left_is_null ? right : left);
4005 frame_->SpillAll();
4006 frame_->EmitPop(eax); 3953 frame_->EmitPop(eax);
4007 __ cmp(eax, Factory::null_value()); 3954 __ cmp(eax, Factory::null_value());
4008 3955
4009 // The 'null' value is only equal to 'undefined' if using non-strict 3956 // The 'null' value is only equal to 'undefined' if using non-strict
4010 // comparisons. 3957 // comparisons.
4011 if (op != Token::EQ_STRICT) { 3958 if (op != Token::EQ_STRICT) {
4012 true_target()->Branch(equal); 3959 true_target()->Branch(equal);
4013 3960
4014 __ cmp(eax, Factory::undefined_value()); 3961 __ cmp(eax, Factory::undefined_value());
4015 true_target()->Branch(equal); 3962 true_target()->Branch(equal);
(...skipping 16 matching lines...) Expand all
4032 // To make typeof testing for natives implemented in JavaScript really 3979 // To make typeof testing for natives implemented in JavaScript really
4033 // efficient, we generate special code for expressions of the form: 3980 // efficient, we generate special code for expressions of the form:
4034 // 'typeof <expression> == <string>'. 3981 // 'typeof <expression> == <string>'.
4035 UnaryOperation* operation = left->AsUnaryOperation(); 3982 UnaryOperation* operation = left->AsUnaryOperation();
4036 if ((op == Token::EQ || op == Token::EQ_STRICT) && 3983 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
4037 (operation != NULL && operation->op() == Token::TYPEOF) && 3984 (operation != NULL && operation->op() == Token::TYPEOF) &&
4038 (right->AsLiteral() != NULL && 3985 (right->AsLiteral() != NULL &&
4039 right->AsLiteral()->handle()->IsString())) { 3986 right->AsLiteral()->handle()->IsString())) {
4040 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3987 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
4041 3988
4042 frame_->SpillAll(); 3989 VirtualFrame::SpilledScope spilled_scope(this);
4043 // Load the operand and move it to register edx. 3990 // Load the operand and move it to register edx.
4044 LoadTypeofExpression(operation->expression()); 3991 LoadTypeofExpression(operation->expression());
4045 frame_->SpillAll();
4046 frame_->EmitPop(edx); 3992 frame_->EmitPop(edx);
4047 3993
4048 if (check->Equals(Heap::number_symbol())) { 3994 if (check->Equals(Heap::number_symbol())) {
4049 __ test(edx, Immediate(kSmiTagMask)); 3995 __ test(edx, Immediate(kSmiTagMask));
4050 true_target()->Branch(zero); 3996 true_target()->Branch(zero);
4051 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3997 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4052 __ cmp(edx, Factory::heap_number_map()); 3998 __ cmp(edx, Factory::heap_number_map());
4053 cc_reg_ = equal; 3999 cc_reg_ = equal;
4054 4000
4055 } else if (check->Equals(Heap::string_symbol())) { 4001 } else if (check->Equals(Heap::string_symbol())) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
4142 case Token::GT: 4088 case Token::GT:
4143 cc = greater; 4089 cc = greater;
4144 break; 4090 break;
4145 case Token::LTE: 4091 case Token::LTE:
4146 cc = less_equal; 4092 cc = less_equal;
4147 break; 4093 break;
4148 case Token::GTE: 4094 case Token::GTE:
4149 cc = greater_equal; 4095 cc = greater_equal;
4150 break; 4096 break;
4151 case Token::IN: { 4097 case Token::IN: {
4152 frame_->SpillAll(); 4098 VirtualFrame::SpilledScope spilled_scope(this);
4153 Load(left); 4099 LoadAndSpill(left);
4154 frame_->SpillAll(); 4100 LoadAndSpill(right);
4155 Load(right);
4156 frame_->SpillAll();
4157 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); 4101 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
4158 frame_->EmitPush(eax); // push the result 4102 frame_->EmitPush(eax); // push the result
4159 return; 4103 return;
4160 } 4104 }
4161 case Token::INSTANCEOF: { 4105 case Token::INSTANCEOF: {
4162 frame_->SpillAll(); 4106 VirtualFrame::SpilledScope spilled_scope(this);
4163 Load(left); 4107 LoadAndSpill(left);
4164 frame_->SpillAll(); 4108 LoadAndSpill(right);
4165 Load(right);
4166 frame_->SpillAll();
4167 InstanceofStub stub; 4109 InstanceofStub stub;
4168 frame_->CallStub(&stub, 2); 4110 frame_->CallStub(&stub, 2);
4169 __ test(eax, Operand(eax)); 4111 __ test(eax, Operand(eax));
4170 cc_reg_ = zero; 4112 cc_reg_ = zero;
4171 return; 4113 return;
4172 } 4114 }
4173 default: 4115 default:
4174 UNREACHABLE(); 4116 UNREACHABLE();
4175 } 4117 }
4176 4118
4177 // Optimize for the case where (at least) one of the expressions 4119 // Optimize for the case where (at least) one of the expressions
4178 // is a literal small integer. 4120 // is a literal small integer.
4179 if (IsInlineSmi(left->AsLiteral())) { 4121 if (IsInlineSmi(left->AsLiteral())) {
4180 frame_->SpillAll();
4181 Load(right); 4122 Load(right);
4182 frame_->SpillAll();
4183 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); 4123 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict);
4184 return; 4124 return;
4185 } 4125 }
4186 if (IsInlineSmi(right->AsLiteral())) { 4126 if (IsInlineSmi(right->AsLiteral())) {
4187 Load(left); 4127 Load(left);
4188 SmiComparison(cc, right->AsLiteral()->handle(), strict); 4128 SmiComparison(cc, right->AsLiteral()->handle(), strict);
4189 return; 4129 return;
4190 } 4130 }
4191 4131
4192 frame_->SpillAll(); 4132 VirtualFrame::SpilledScope spilled_scope(this);
4193 Load(left); 4133 LoadAndSpill(left);
4194 frame_->SpillAll(); 4134 LoadAndSpill(right);
4195 Load(right);
4196 frame_->SpillAll();
4197 Comparison(cc, strict); 4135 Comparison(cc, strict);
4198 } 4136 }
4199 4137
4200 4138
4201 void CodeGenerator::RecordStatementPosition(Node* node) { 4139 void CodeGenerator::RecordStatementPosition(Node* node) {
4202 if (FLAG_debug_info) { 4140 if (FLAG_debug_info) {
4203 int pos = node->statement_pos(); 4141 int pos = node->statement_pos();
4204 if (pos != RelocInfo::kNoPosition) { 4142 if (pos != RelocInfo::kNoPosition) {
4205 __ RecordStatementPosition(pos); 4143 __ RecordStatementPosition(pos);
4206 } 4144 }
(...skipping 22 matching lines...) Expand all
4229 MacroAssembler* masm = cgen_->masm(); 4167 MacroAssembler* masm = cgen_->masm();
4230 __ RecordPosition(property->position()); 4168 __ RecordPosition(property->position());
4231 Literal* raw_name = property->key()->AsLiteral(); 4169 Literal* raw_name = property->key()->AsLiteral();
4232 ASSERT(raw_name != NULL); 4170 ASSERT(raw_name != NULL);
4233 return Handle<String>(String::cast(*raw_name->handle())); 4171 return Handle<String>(String::cast(*raw_name->handle()));
4234 } 4172 }
4235 } 4173 }
4236 4174
4237 4175
4238 void Reference::GetValue(TypeofState typeof_state) { 4176 void Reference::GetValue(TypeofState typeof_state) {
4177 ASSERT(!cgen_->in_spilled_code());
4239 ASSERT(!is_illegal()); 4178 ASSERT(!is_illegal());
4240 ASSERT(!cgen_->has_cc()); 4179 ASSERT(!cgen_->has_cc());
4241 MacroAssembler* masm = cgen_->masm(); 4180 MacroAssembler* masm = cgen_->masm();
4242 VirtualFrame* frame = cgen_->frame(); 4181 VirtualFrame* frame = cgen_->frame();
4243 switch (type_) { 4182 switch (type_) {
4244 case SLOT: { 4183 case SLOT: {
4245 Comment cmnt(masm, "[ Load from Slot"); 4184 Comment cmnt(masm, "[ Load from Slot");
4246 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4185 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4247 ASSERT(slot != NULL); 4186 ASSERT(slot != NULL);
4248 cgen_->LoadFromSlot(slot, typeof_state); 4187 cgen_->LoadFromSlot(slot, typeof_state);
4249 break; 4188 break;
4250 } 4189 }
4251 4190
4252 case NAMED: { 4191 case NAMED: {
4253 // TODO(1241834): Make sure that this it is safe to ignore the 4192 // TODO(1241834): Make sure that this it is safe to ignore the
4254 // distinction between expressions in a typeof and not in a typeof. If 4193 // distinction between expressions in a typeof and not in a typeof. If
4255 // there is a chance that reference errors can be thrown below, we 4194 // there is a chance that reference errors can be thrown below, we
4256 // must distinguish between the two kinds of loads (typeof expression 4195 // must distinguish between the two kinds of loads (typeof expression
4257 // loads must not throw a reference error). 4196 // loads must not throw a reference error).
4258 frame->SpillAll(); 4197 VirtualFrame::SpilledScope spilled_scope(cgen_);
4259 Comment cmnt(masm, "[ Load from named Property"); 4198 Comment cmnt(masm, "[ Load from named Property");
4260 Handle<String> name(GetName()); 4199 Handle<String> name(GetName());
4261 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 4200 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
4262 // Setup the name register. 4201 // Setup the name register.
4263 __ mov(ecx, name); 4202 __ mov(ecx, name);
4264 4203
4265 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4204 Variable* var = expression_->AsVariableProxy()->AsVariable();
4266 if (var != NULL) { 4205 if (var != NULL) {
4267 ASSERT(var->is_global()); 4206 ASSERT(var->is_global());
4268 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4207 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4269 } else { 4208 } else {
4270 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4209 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4271 } 4210 }
4272 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4211 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4273 break; 4212 break;
4274 } 4213 }
4275 4214
4276 case KEYED: { 4215 case KEYED: {
4277 // TODO(1241834): Make sure that this it is safe to ignore the 4216 // TODO(1241834): Make sure that this it is safe to ignore the
4278 // distinction between expressions in a typeof and not in a typeof. 4217 // distinction between expressions in a typeof and not in a typeof.
4279 frame->SpillAll(); 4218 VirtualFrame::SpilledScope spilled_scope(cgen_);
4280 Comment cmnt(masm, "[ Load from keyed Property"); 4219 Comment cmnt(masm, "[ Load from keyed Property");
4281 Property* property = expression_->AsProperty(); 4220 Property* property = expression_->AsProperty();
4282 ASSERT(property != NULL); 4221 ASSERT(property != NULL);
4283 __ RecordPosition(property->position()); 4222 __ RecordPosition(property->position());
4284 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 4223 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4285 4224
4286 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4225 Variable* var = expression_->AsVariableProxy()->AsVariable();
4287 if (var != NULL) { 4226 if (var != NULL) {
4288 ASSERT(var->is_global()); 4227 ASSERT(var->is_global());
4289 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4228 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
(...skipping 18 matching lines...) Expand all
4308 switch (type_) { 4247 switch (type_) {
4309 case SLOT: { 4248 case SLOT: {
4310 Comment cmnt(masm, "[ Store to Slot"); 4249 Comment cmnt(masm, "[ Store to Slot");
4311 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4250 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4312 ASSERT(slot != NULL); 4251 ASSERT(slot != NULL);
4313 cgen_->StoreToSlot(slot, init_state); 4252 cgen_->StoreToSlot(slot, init_state);
4314 break; 4253 break;
4315 } 4254 }
4316 4255
4317 case NAMED: { 4256 case NAMED: {
4318 frame->SpillAll(); 4257 VirtualFrame::SpilledScope spilled_scope(cgen_);
4319 Comment cmnt(masm, "[ Store to named Property"); 4258 Comment cmnt(masm, "[ Store to named Property");
4320 // Call the appropriate IC code. 4259 // Call the appropriate IC code.
4321 Handle<String> name(GetName()); 4260 Handle<String> name(GetName());
4322 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4261 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4323 // TODO(1222589): Make the IC grab the values from the stack. 4262 // TODO(1222589): Make the IC grab the values from the stack.
4324 frame->EmitPop(eax); 4263 frame->EmitPop(eax);
4325 // Setup the name register. 4264 // Setup the name register.
4326 __ mov(ecx, name); 4265 __ mov(ecx, name);
4327 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4266 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4328 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4267 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4329 break; 4268 break;
4330 } 4269 }
4331 4270
4332 case KEYED: { 4271 case KEYED: {
4333 frame->SpillAll(); 4272 VirtualFrame::SpilledScope spilled_scope(cgen_);
4334 Comment cmnt(masm, "[ Store to keyed Property"); 4273 Comment cmnt(masm, "[ Store to keyed Property");
4335 Property* property = expression_->AsProperty(); 4274 Property* property = expression_->AsProperty();
4336 ASSERT(property != NULL); 4275 ASSERT(property != NULL);
4337 __ RecordPosition(property->position()); 4276 __ RecordPosition(property->position());
4338 // Call IC code. 4277 // Call IC code.
4339 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4278 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4340 // TODO(1222589): Make the IC grab the values from the stack. 4279 // TODO(1222589): Make the IC grab the values from the stack.
4341 frame->EmitPop(eax); 4280 frame->EmitPop(eax);
4342 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4281 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4343 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4282 frame->EmitPush(eax); // IC call leaves result in eax, push it out
(...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after
5724 5663
5725 // Slow-case: Go through the JavaScript implementation. 5664 // Slow-case: Go through the JavaScript implementation.
5726 __ bind(&slow); 5665 __ bind(&slow);
5727 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5666 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5728 } 5667 }
5729 5668
5730 5669
5731 #undef __ 5670 #undef __
5732 5671
5733 } } // namespace v8::internal 5672 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698