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

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

Issue 192513002: Checking for stack height equality between full codegen and hydrogen. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.cc ('k') | src/objects.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "v8.h" 5 #include "v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "code-stubs.h" 9 #include "code-stubs.h"
10 #include "codegen.h" 10 #include "codegen.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 158
159 info->set_prologue_offset(masm_->pc_offset()); 159 info->set_prologue_offset(masm_->pc_offset());
160 __ Prologue(info->IsCodePreAgingActive()); 160 __ Prologue(info->IsCodePreAgingActive());
161 info->AddNoFrameRange(0, masm_->pc_offset()); 161 info->AddNoFrameRange(0, masm_->pc_offset());
162 162
163 { Comment cmnt(masm_, "[ Allocate locals"); 163 { Comment cmnt(masm_, "[ Allocate locals");
164 int locals_count = info->scope()->num_stack_slots(); 164 int locals_count = info->scope()->num_stack_slots();
165 // Generators allocate locals, if any, in context slots. 165 // Generators allocate locals, if any, in context slots.
166 ASSERT(!info->function()->is_generator() || locals_count == 0); 166 ASSERT(!info->function()->is_generator() || locals_count == 0);
167 if (locals_count == 1) { 167 if (locals_count == 1) {
168 __ push(Immediate(isolate()->factory()->undefined_value())); 168 AsmPushHandle(isolate()->factory()->undefined_value());
169 } else if (locals_count > 1) { 169 } else if (locals_count > 1) {
170 if (locals_count >= 128) { 170 if (locals_count >= 128) {
171 EmitStackCheck(masm_, locals_count, ecx); 171 EmitStackCheck(masm_, locals_count, ecx);
172 } 172 }
173 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); 173 __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
174 const int kMaxPushes = 32; 174 const int kMaxPushes = 32;
175 if (locals_count >= kMaxPushes) { 175 if (locals_count >= kMaxPushes) {
176 int loop_iterations = locals_count / kMaxPushes; 176 int loop_iterations = locals_count / kMaxPushes;
177 __ mov(ecx, loop_iterations); 177 __ mov(ecx, loop_iterations);
178 Label loop_header; 178 Label loop_header;
179 __ bind(&loop_header); 179 __ bind(&loop_header);
180 // Do pushes. 180 // Do pushes.
181 for (int i = 0; i < kMaxPushes; i++) { 181 for (int i = 0; i < kMaxPushes; i++) {
182 __ push(eax); 182 __ push(eax);
183 } 183 }
184 __ dec(ecx); 184 __ dec(ecx);
185 __ j(not_zero, &loop_header, Label::kNear); 185 __ j(not_zero, &loop_header, Label::kNear);
186 } 186 }
187 int remaining = locals_count % kMaxPushes; 187 int remaining = locals_count % kMaxPushes;
188 // Emit the remaining pushes. 188 // Emit the remaining pushes.
189 for (int i = 0; i < remaining; i++) { 189 for (int i = 0; i < remaining; i++) {
190 __ push(eax); 190 __ push(eax);
191 } 191 }
192 UpdateStackHeight(locals_count);
192 } 193 }
193 } 194 }
194 195
195 bool function_in_register = true; 196 bool function_in_register = true;
196 197
197 // Possibly allocate a local context. 198 // Possibly allocate a local context.
198 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 199 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
199 if (heap_slots > 0) { 200 if (heap_slots > 0) {
200 Comment cmnt(masm_, "[ Allocate context"); 201 Comment cmnt(masm_, "[ Allocate context");
201 // Argument to NewContext is the function, which is still in edi. 202 // Argument to NewContext is the function, which is still in edi.
202 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 203 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
203 __ push(edi); 204 AsmPush(edi);
204 __ Push(info->scope()->GetScopeInfo()); 205 AsmPushHandle(info->scope()->GetScopeInfo());
205 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); 206 AsmCallRuntime(Runtime::kHiddenNewGlobalContext, 2);
206 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 207 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
207 FastNewContextStub stub(isolate(), heap_slots); 208 FastNewContextStub stub(isolate(), heap_slots);
208 __ CallStub(&stub); 209 __ CallStub(&stub);
209 } else { 210 } else {
210 __ push(edi); 211 AsmPush(edi);
211 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); 212 AsmCallRuntime(Runtime::kHiddenNewFunctionContext, 1);
212 } 213 }
213 function_in_register = false; 214 function_in_register = false;
214 // Context is returned in eax. It replaces the context passed to us. 215 // Context is returned in eax. It replaces the context passed to us.
215 // It's saved in the stack and kept live in esi. 216 // It's saved in the stack and kept live in esi.
216 __ mov(esi, eax); 217 __ mov(esi, eax);
217 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); 218 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
218 219
219 // Copy parameters into context if necessary. 220 // Copy parameters into context if necessary.
220 int num_parameters = info->scope()->num_parameters(); 221 int num_parameters = info->scope()->num_parameters();
221 for (int i = 0; i < num_parameters; i++) { 222 for (int i = 0; i < num_parameters; i++) {
(...skipping 14 matching lines...) Expand all
236 kDontSaveFPRegs); 237 kDontSaveFPRegs);
237 } 238 }
238 } 239 }
239 } 240 }
240 241
241 Variable* arguments = scope()->arguments(); 242 Variable* arguments = scope()->arguments();
242 if (arguments != NULL) { 243 if (arguments != NULL) {
243 // Function uses arguments object. 244 // Function uses arguments object.
244 Comment cmnt(masm_, "[ Allocate arguments object"); 245 Comment cmnt(masm_, "[ Allocate arguments object");
245 if (function_in_register) { 246 if (function_in_register) {
246 __ push(edi); 247 AsmPush(edi);
247 } else { 248 } else {
248 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 249 AsmPush(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
249 } 250 }
250 // Receiver is just before the parameters on the caller's stack. 251 // Receiver is just before the parameters on the caller's stack.
251 int num_parameters = info->scope()->num_parameters(); 252 int num_parameters = info->scope()->num_parameters();
252 int offset = num_parameters * kPointerSize; 253 int offset = num_parameters * kPointerSize;
253 __ lea(edx, 254 __ lea(edx,
254 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 255 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
255 __ push(edx); 256 AsmPush(edx);
256 __ push(Immediate(Smi::FromInt(num_parameters))); 257 AsmPushSmi(Smi::FromInt(num_parameters));
257 // Arguments to ArgumentsAccessStub: 258 // Arguments to ArgumentsAccessStub:
258 // function, receiver address, parameter count. 259 // function, receiver address, parameter count.
259 // The stub will rewrite receiver and parameter count if the previous 260 // The stub will rewrite receiver and parameter count if the previous
260 // stack frame was an arguments adapter frame. 261 // stack frame was an arguments adapter frame.
261 ArgumentsAccessStub::Type type; 262 ArgumentsAccessStub::Type type;
262 if (strict_mode() == STRICT) { 263 if (strict_mode() == STRICT) {
263 type = ArgumentsAccessStub::NEW_STRICT; 264 type = ArgumentsAccessStub::NEW_STRICT;
264 } else if (function()->has_duplicate_parameters()) { 265 } else if (function()->has_duplicate_parameters()) {
265 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; 266 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
266 } else { 267 } else {
267 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; 268 type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
268 } 269 }
269 ArgumentsAccessStub stub(isolate(), type); 270 ArgumentsAccessStub stub(isolate(), type);
270 __ CallStub(&stub); 271 AsmCallStub(&stub, 3);
271 272
272 SetVar(arguments, eax, ebx, edx); 273 SetVar(arguments, eax, ebx, edx);
273 } 274 }
274 275
275 if (FLAG_trace) { 276 if (FLAG_trace) {
276 __ CallRuntime(Runtime::kTraceEnter, 0); 277 AsmCallRuntime(Runtime::kTraceEnter, 0);
277 } 278 }
278 279
279 // Visit the declarations and body unless there is an illegal 280 // Visit the declarations and body unless there is an illegal
280 // redeclaration. 281 // redeclaration.
281 if (scope()->HasIllegalRedeclaration()) { 282 if (scope()->HasIllegalRedeclaration()) {
282 Comment cmnt(masm_, "[ Declarations"); 283 Comment cmnt(masm_, "[ Declarations");
283 scope()->VisitIllegalRedeclaration(this); 284 scope()->VisitIllegalRedeclaration(this);
284 285
285 } else { 286 } else {
286 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 287 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 369
369 370
370 void FullCodeGenerator::EmitReturnSequence() { 371 void FullCodeGenerator::EmitReturnSequence() {
371 Comment cmnt(masm_, "[ Return sequence"); 372 Comment cmnt(masm_, "[ Return sequence");
372 if (return_label_.is_bound()) { 373 if (return_label_.is_bound()) {
373 __ jmp(&return_label_); 374 __ jmp(&return_label_);
374 } else { 375 } else {
375 // Common return label 376 // Common return label
376 __ bind(&return_label_); 377 __ bind(&return_label_);
377 if (FLAG_trace) { 378 if (FLAG_trace) {
378 __ push(eax); 379 AsmPush(eax);
379 __ CallRuntime(Runtime::kTraceExit, 1); 380 AsmCallRuntime(Runtime::kTraceExit, 1);
380 } 381 }
381 // Pretend that the exit is a backwards jump to the entry. 382 // Pretend that the exit is a backwards jump to the entry.
382 int weight = 1; 383 int weight = 1;
383 if (info_->ShouldSelfOptimize()) { 384 if (info_->ShouldSelfOptimize()) {
384 weight = FLAG_interrupt_budget / FLAG_self_opt_count; 385 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
385 } else { 386 } else {
386 int distance = masm_->pc_offset(); 387 int distance = masm_->pc_offset();
387 weight = Min(kMaxBackEdgeWeight, 388 weight = Min(kMaxBackEdgeWeight,
388 Max(1, distance / kCodeSizeMultiplier)); 389 Max(1, distance / kCodeSizeMultiplier));
389 } 390 }
390 EmitProfilingCounterDecrement(weight); 391 EmitProfilingCounterDecrement(weight);
391 Label ok; 392 Label ok;
392 __ j(positive, &ok, Label::kNear); 393 __ j(positive, &ok, Label::kNear);
393 __ push(eax); 394 AsmPush(eax);
394 __ call(isolate()->builtins()->InterruptCheck(), 395 __ call(isolate()->builtins()->InterruptCheck(),
395 RelocInfo::CODE_TARGET); 396 RelocInfo::CODE_TARGET);
396 __ pop(eax); 397 AsmPop(eax);
397 EmitProfilingCounterReset(); 398 EmitProfilingCounterReset();
398 __ bind(&ok); 399 __ bind(&ok);
399 #ifdef DEBUG 400 #ifdef DEBUG
400 // Add a label for checking the size of the code used for returning. 401 // Add a label for checking the size of the code used for returning.
401 Label check_exit_codesize; 402 Label check_exit_codesize;
402 masm_->bind(&check_exit_codesize); 403 masm_->bind(&check_exit_codesize);
403 #endif 404 #endif
404 SetSourcePosition(function()->end_position() - 1); 405 SetSourcePosition(function()->end_position() - 1);
405 __ RecordJSReturn(); 406 __ RecordJSReturn();
406 // Do not use the leave instruction here because it is too short to 407 // Do not use the leave instruction here because it is too short to
(...skipping 21 matching lines...) Expand all
428 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 429 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
429 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 430 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
430 codegen()->GetVar(result_register(), var); 431 codegen()->GetVar(result_register(), var);
431 } 432 }
432 433
433 434
434 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 435 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
435 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 436 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
436 MemOperand operand = codegen()->VarOperand(var, result_register()); 437 MemOperand operand = codegen()->VarOperand(var, result_register());
437 // Memory operands can be pushed directly. 438 // Memory operands can be pushed directly.
438 __ push(operand); 439 codegen()->AsmPush(operand);
439 } 440 }
440 441
441 442
442 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 443 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
443 // For simplicity we always test the accumulator register. 444 // For simplicity we always test the accumulator register.
444 codegen()->GetVar(result_register(), var); 445 codegen()->GetVar(result_register(), var);
445 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 446 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
446 codegen()->DoTest(this); 447 codegen()->DoTest(this);
447 } 448 }
448 449
(...skipping 30 matching lines...) Expand all
479 __ SafeMove(result_register(), Immediate(lit)); 480 __ SafeMove(result_register(), Immediate(lit));
480 } else { 481 } else {
481 __ Move(result_register(), Immediate(lit)); 482 __ Move(result_register(), Immediate(lit));
482 } 483 }
483 } 484 }
484 485
485 486
486 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 487 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
487 if (lit->IsSmi()) { 488 if (lit->IsSmi()) {
488 __ SafePush(Immediate(lit)); 489 __ SafePush(Immediate(lit));
490 codegen()->UpdateStackHeight(1);
489 } else { 491 } else {
490 __ push(Immediate(lit)); 492 codegen()->AsmPushHandle(lit);
491 } 493 }
492 } 494 }
493 495
494 496
495 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 497 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
496 codegen()->PrepareForBailoutBeforeSplit(condition(), 498 codegen()->PrepareForBailoutBeforeSplit(condition(),
497 true, 499 true,
498 true_label_, 500 true_label_,
499 false_label_); 501 false_label_);
500 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 502 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
(...skipping 17 matching lines...) Expand all
518 // For simplicity we always test the accumulator register. 520 // For simplicity we always test the accumulator register.
519 __ mov(result_register(), lit); 521 __ mov(result_register(), lit);
520 codegen()->DoTest(this); 522 codegen()->DoTest(this);
521 } 523 }
522 } 524 }
523 525
524 526
525 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 527 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
526 Register reg) const { 528 Register reg) const {
527 ASSERT(count > 0); 529 ASSERT(count > 0);
528 __ Drop(count); 530 codegen()->AsmDrop(count);
529 } 531 }
530 532
531 533
532 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 534 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
533 int count, 535 int count,
534 Register reg) const { 536 Register reg) const {
535 ASSERT(count > 0); 537 ASSERT(count > 0);
536 __ Drop(count); 538 codegen()->AsmDrop(count);
537 __ Move(result_register(), reg); 539 __ Move(result_register(), reg);
538 } 540 }
539 541
540 542
541 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, 543 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
542 Register reg) const { 544 Register reg) const {
543 ASSERT(count > 0); 545 ASSERT(count > 0);
544 if (count > 1) __ Drop(count - 1); 546 if (count > 1) codegen()->AsmDrop(count - 1);
545 __ mov(Operand(esp, 0), reg); 547 __ mov(Operand(esp, 0), reg);
546 } 548 }
547 549
548 550
549 void FullCodeGenerator::TestContext::DropAndPlug(int count, 551 void FullCodeGenerator::TestContext::DropAndPlug(int count,
550 Register reg) const { 552 Register reg) const {
551 ASSERT(count > 0); 553 ASSERT(count > 0);
552 // For simplicity we always test the accumulator register. 554 // For simplicity we always test the accumulator register.
553 __ Drop(count); 555 codegen()->AsmDrop(count);
554 __ Move(result_register(), reg); 556 __ Move(result_register(), reg);
555 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 557 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
556 codegen()->DoTest(this); 558 codegen()->DoTest(this);
557 } 559 }
558 560
559 561
560 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 562 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
561 Label* materialize_false) const { 563 Label* materialize_false) const {
562 ASSERT(materialize_true == materialize_false); 564 ASSERT(materialize_true == materialize_false);
563 __ bind(materialize_true); 565 __ bind(materialize_true);
564 } 566 }
565 567
566 568
567 void FullCodeGenerator::AccumulatorValueContext::Plug( 569 void FullCodeGenerator::AccumulatorValueContext::Plug(
568 Label* materialize_true, 570 Label* materialize_true,
569 Label* materialize_false) const { 571 Label* materialize_false) const {
570 Label done; 572 Label done;
571 __ bind(materialize_true); 573 __ bind(materialize_true);
572 __ mov(result_register(), isolate()->factory()->true_value()); 574 __ mov(result_register(), isolate()->factory()->true_value());
573 __ jmp(&done, Label::kNear); 575 __ jmp(&done, Label::kNear);
574 __ bind(materialize_false); 576 __ bind(materialize_false);
575 __ mov(result_register(), isolate()->factory()->false_value()); 577 __ mov(result_register(), isolate()->factory()->false_value());
576 __ bind(&done); 578 __ bind(&done);
577 } 579 }
578 580
579 581
580 void FullCodeGenerator::StackValueContext::Plug( 582 void FullCodeGenerator::StackValueContext::Plug(
581 Label* materialize_true, 583 Label* materialize_true,
582 Label* materialize_false) const { 584 Label* materialize_false) const {
585 StackHeightWrapper stack_height = codegen()->CurrentStackHeight();
583 Label done; 586 Label done;
584 __ bind(materialize_true); 587 __ bind(materialize_true);
585 __ push(Immediate(isolate()->factory()->true_value())); 588 codegen()->AsmPushHandle(isolate()->factory()->true_value());
586 __ jmp(&done, Label::kNear); 589 __ jmp(&done, Label::kNear);
587 __ bind(materialize_false); 590 __ bind(materialize_false);
588 __ push(Immediate(isolate()->factory()->false_value())); 591 codegen()->SetStackHeight(stack_height);
592 codegen()->AsmPushHandle(isolate()->factory()->false_value());
589 __ bind(&done); 593 __ bind(&done);
590 } 594 }
591 595
592 596
593 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 597 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
594 Label* materialize_false) const { 598 Label* materialize_false) const {
595 ASSERT(materialize_true == true_label_); 599 ASSERT(materialize_true == true_label_);
596 ASSERT(materialize_false == false_label_); 600 ASSERT(materialize_false == false_label_);
597 } 601 }
598 602
599 603
600 void FullCodeGenerator::EffectContext::Plug(bool flag) const { 604 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
601 } 605 }
602 606
603 607
604 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 608 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
605 Handle<Object> value = flag 609 Handle<Object> value = flag
606 ? isolate()->factory()->true_value() 610 ? isolate()->factory()->true_value()
607 : isolate()->factory()->false_value(); 611 : isolate()->factory()->false_value();
608 __ mov(result_register(), value); 612 __ mov(result_register(), value);
609 } 613 }
610 614
611 615
612 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 616 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
613 Handle<Object> value = flag 617 Handle<Object> value = flag
614 ? isolate()->factory()->true_value() 618 ? isolate()->factory()->true_value()
615 : isolate()->factory()->false_value(); 619 : isolate()->factory()->false_value();
616 __ push(Immediate(value)); 620 codegen()->AsmPushHandle(value);
617 } 621 }
618 622
619 623
620 void FullCodeGenerator::TestContext::Plug(bool flag) const { 624 void FullCodeGenerator::TestContext::Plug(bool flag) const {
621 codegen()->PrepareForBailoutBeforeSplit(condition(), 625 codegen()->PrepareForBailoutBeforeSplit(condition(),
622 true, 626 true,
623 true_label_, 627 true_label_,
624 false_label_); 628 false_label_);
625 if (flag) { 629 if (flag) {
626 if (true_label_ != fall_through_) __ jmp(true_label_); 630 if (true_label_ != fall_through_) __ jmp(true_label_);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 EmitDebugCheckDeclarationContext(variable); 780 EmitDebugCheckDeclarationContext(variable);
777 __ mov(ContextOperand(esi, variable->index()), 781 __ mov(ContextOperand(esi, variable->index()),
778 Immediate(isolate()->factory()->the_hole_value())); 782 Immediate(isolate()->factory()->the_hole_value()));
779 // No write barrier since the hole value is in old space. 783 // No write barrier since the hole value is in old space.
780 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 784 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
781 } 785 }
782 break; 786 break;
783 787
784 case Variable::LOOKUP: { 788 case Variable::LOOKUP: {
785 Comment cmnt(masm_, "[ VariableDeclaration"); 789 Comment cmnt(masm_, "[ VariableDeclaration");
786 __ push(esi); 790 AsmPush(esi);
787 __ push(Immediate(variable->name())); 791 AsmPushHandle(variable->name());
788 // VariableDeclaration nodes are always introduced in one of four modes. 792 // VariableDeclaration nodes are always introduced in one of four modes.
789 ASSERT(IsDeclaredVariableMode(mode)); 793 ASSERT(IsDeclaredVariableMode(mode));
790 PropertyAttributes attr = 794 PropertyAttributes attr =
791 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; 795 IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
792 __ push(Immediate(Smi::FromInt(attr))); 796 AsmPushSmi(Smi::FromInt(attr));
793 // Push initial value, if any. 797 // Push initial value, if any.
794 // Note: For variables we must not push an initial value (such as 798 // Note: For variables we must not push an initial value (such as
795 // 'undefined') because we may have a (legal) redeclaration and we 799 // 'undefined') because we may have a (legal) redeclaration and we
796 // must not destroy the current value. 800 // must not destroy the current value.
797 if (hole_init) { 801 if (hole_init) {
798 __ push(Immediate(isolate()->factory()->the_hole_value())); 802 AsmPushHandle(isolate()->factory()->the_hole_value());
799 } else { 803 } else {
800 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. 804 AsmPushSmi(Smi::FromInt(0)); // Indicates no initial value.
801 } 805 }
802 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); 806 AsmCallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
803 break; 807 break;
804 } 808 }
805 } 809 }
806 } 810 }
807 811
808 812
809 void FullCodeGenerator::VisitFunctionDeclaration( 813 void FullCodeGenerator::VisitFunctionDeclaration(
810 FunctionDeclaration* declaration) { 814 FunctionDeclaration* declaration) {
811 VariableProxy* proxy = declaration->proxy(); 815 VariableProxy* proxy = declaration->proxy();
812 Variable* variable = proxy->var(); 816 Variable* variable = proxy->var();
(...skipping 28 matching lines...) Expand all
841 ecx, 845 ecx,
842 kDontSaveFPRegs, 846 kDontSaveFPRegs,
843 EMIT_REMEMBERED_SET, 847 EMIT_REMEMBERED_SET,
844 OMIT_SMI_CHECK); 848 OMIT_SMI_CHECK);
845 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 849 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
846 break; 850 break;
847 } 851 }
848 852
849 case Variable::LOOKUP: { 853 case Variable::LOOKUP: {
850 Comment cmnt(masm_, "[ FunctionDeclaration"); 854 Comment cmnt(masm_, "[ FunctionDeclaration");
851 __ push(esi); 855 AsmPush(esi);
852 __ push(Immediate(variable->name())); 856 AsmPushHandle(variable->name());
853 __ push(Immediate(Smi::FromInt(NONE))); 857 AsmPushSmi(Smi::FromInt(NONE));
854 VisitForStackValue(declaration->fun()); 858 VisitForStackValue(declaration->fun());
855 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); 859 AsmCallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
856 break; 860 break;
857 } 861 }
858 } 862 }
859 } 863 }
860 864
861 865
862 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 866 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
863 Variable* variable = declaration->proxy()->var(); 867 Variable* variable = declaration->proxy()->var();
864 ASSERT(variable->location() == Variable::CONTEXT); 868 ASSERT(variable->location() == Variable::CONTEXT);
865 ASSERT(variable->interface()->IsFrozen()); 869 ASSERT(variable->interface()->IsFrozen());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 } 916 }
913 917
914 918
915 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { 919 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
916 // TODO(rossberg) 920 // TODO(rossberg)
917 } 921 }
918 922
919 923
920 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 924 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
921 // Call the runtime to declare the globals. 925 // Call the runtime to declare the globals.
922 __ push(esi); // The context is the first argument. 926 AsmPush(esi); // The context is the first argument.
923 __ Push(pairs); 927 AsmPushHandle(pairs);
924 __ Push(Smi::FromInt(DeclareGlobalsFlags())); 928 AsmPushSmi(Smi::FromInt(DeclareGlobalsFlags()));
925 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); 929 AsmCallRuntime(Runtime::kHiddenDeclareGlobals, 3);
926 // Return value is ignored. 930 // Return value is ignored.
927 } 931 }
928 932
929 933
930 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { 934 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
931 // Call the runtime to declare the modules. 935 // Call the runtime to declare the modules.
932 __ Push(descriptions); 936 AsmPushHandle(descriptions);
933 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); 937 AsmCallRuntime(Runtime::kHiddenDeclareModules, 1);
934 // Return value is ignored. 938 // Return value is ignored.
935 } 939 }
936 940
937 941
938 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 942 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
939 Comment cmnt(masm_, "[ SwitchStatement"); 943 Comment cmnt(masm_, "[ SwitchStatement");
940 Breakable nested_statement(this, stmt); 944 Breakable nested_statement(this, stmt);
941 SetStatementPosition(stmt); 945 SetStatementPosition(stmt);
942 946
943 // Keep the switch value on the stack until a case matches. 947 // Keep the switch value on the stack until a case matches.
944 VisitForStackValue(stmt->tag()); 948 VisitForStackValue(stmt->tag());
945 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 949 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
946 950
947 ZoneList<CaseClause*>* clauses = stmt->cases(); 951 ZoneList<CaseClause*>* clauses = stmt->cases();
948 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 952 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
949 953
954 StackHeightWrapper case_stack_height = CurrentStackHeight();
950 Label next_test; // Recycled for each test. 955 Label next_test; // Recycled for each test.
951 // Compile all the tests with branches to their bodies. 956 // Compile all the tests with branches to their bodies.
952 for (int i = 0; i < clauses->length(); i++) { 957 for (int i = 0; i < clauses->length(); i++) {
953 CaseClause* clause = clauses->at(i); 958 CaseClause* clause = clauses->at(i);
954 clause->body_target()->Unuse(); 959 clause->body_target()->Unuse();
955 960
956 // The default is not a test, but remember it as final fall through. 961 // The default is not a test, but remember it as final fall through.
957 if (clause->is_default()) { 962 if (clause->is_default()) {
958 default_clause = clause; 963 default_clause = clause;
959 continue; 964 continue;
960 } 965 }
961 966
962 Comment cmnt(masm_, "[ Case comparison"); 967 Comment cmnt(masm_, "[ Case comparison");
963 __ bind(&next_test); 968 __ bind(&next_test);
969 SetStackHeight(case_stack_height);
964 next_test.Unuse(); 970 next_test.Unuse();
965 971
966 // Compile the label expression. 972 // Compile the label expression.
967 VisitForAccumulatorValue(clause->label()); 973 VisitForAccumulatorValue(clause->label());
968 974
969 // Perform the comparison as if via '==='. 975 // Perform the comparison as if via '==='.
970 __ mov(edx, Operand(esp, 0)); // Switch value. 976 __ mov(edx, Operand(esp, 0)); // Switch value.
971 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 977 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
972 JumpPatchSite patch_site(masm_); 978 JumpPatchSite patch_site(masm_);
973 if (inline_smi_code) { 979 if (inline_smi_code) {
974 Label slow_case; 980 Label slow_case;
975 __ mov(ecx, edx); 981 __ mov(ecx, edx);
976 __ or_(ecx, eax); 982 __ or_(ecx, eax);
977 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 983 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
978 984
979 __ cmp(edx, eax); 985 __ cmp(edx, eax);
980 __ j(not_equal, &next_test); 986 __ j(not_equal, &next_test);
981 __ Drop(1); // Switch value is no longer needed. 987 AsmDrop(1); // Switch value is no longer needed.
982 __ jmp(clause->body_target()); 988 __ jmp(clause->body_target());
983 __ bind(&slow_case); 989 __ bind(&slow_case);
990 SetStackHeight(case_stack_height);
984 } 991 }
985 992
986 // Record position before stub call for type feedback. 993 // Record position before stub call for type feedback.
987 SetSourcePosition(clause->position()); 994 SetSourcePosition(clause->position());
988 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 995 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
989 CallIC(ic, clause->CompareId()); 996 CallIC(ic, clause->CompareId());
990 patch_site.EmitPatchInfo(); 997 patch_site.EmitPatchInfo();
991 998
992 Label skip; 999 Label skip;
993 __ jmp(&skip, Label::kNear); 1000 __ jmp(&skip, Label::kNear);
994 PrepareForBailout(clause, TOS_REG); 1001 PrepareForBailout(clause, TOS_REG);
1002
1003 ASSERT(case_stack_height.get() == stack_height_.get());
995 __ cmp(eax, isolate()->factory()->true_value()); 1004 __ cmp(eax, isolate()->factory()->true_value());
996 __ j(not_equal, &next_test); 1005 __ j(not_equal, &next_test);
997 __ Drop(1); 1006 AsmDrop(1);
998 __ jmp(clause->body_target()); 1007 __ jmp(clause->body_target());
999 __ bind(&skip); 1008 __ bind(&skip);
1009 SetStackHeight(case_stack_height);
1000 1010
1001 __ test(eax, eax); 1011 __ test(eax, eax);
1002 __ j(not_equal, &next_test); 1012 __ j(not_equal, &next_test);
1003 __ Drop(1); // Switch value is no longer needed. 1013 AsmDrop(1); // Switch value is no longer needed.
1004 __ jmp(clause->body_target()); 1014 __ jmp(clause->body_target());
1005 } 1015 }
1006 1016
1007 // Discard the test value and jump to the default if present, otherwise to 1017 // Discard the test value and jump to the default if present, otherwise to
1008 // the end of the statement. 1018 // the end of the statement.
1009 __ bind(&next_test); 1019 __ bind(&next_test);
1010 __ Drop(1); // Switch value is no longer needed. 1020 SetStackHeight(case_stack_height);
1021 AsmDrop(1); // Switch value is no longer needed.
1011 if (default_clause == NULL) { 1022 if (default_clause == NULL) {
1012 __ jmp(nested_statement.break_label()); 1023 __ jmp(nested_statement.break_label());
1013 } else { 1024 } else {
1014 __ jmp(default_clause->body_target()); 1025 __ jmp(default_clause->body_target());
1015 } 1026 }
1016 1027
1017 // Compile all the case bodies. 1028 // Compile all the case bodies.
1018 for (int i = 0; i < clauses->length(); i++) { 1029 for (int i = 0; i < clauses->length(); i++) {
1019 Comment cmnt(masm_, "[ Case body"); 1030 Comment cmnt(masm_, "[ Case body");
1020 CaseClause* clause = clauses->at(i); 1031 CaseClause* clause = clauses->at(i);
(...skipping 26 matching lines...) Expand all
1047 __ j(equal, &exit); 1058 __ j(equal, &exit);
1048 1059
1049 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 1060 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1050 1061
1051 // Convert the object to a JS object. 1062 // Convert the object to a JS object.
1052 Label convert, done_convert; 1063 Label convert, done_convert;
1053 __ JumpIfSmi(eax, &convert, Label::kNear); 1064 __ JumpIfSmi(eax, &convert, Label::kNear);
1054 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1065 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1055 __ j(above_equal, &done_convert, Label::kNear); 1066 __ j(above_equal, &done_convert, Label::kNear);
1056 __ bind(&convert); 1067 __ bind(&convert);
1057 __ push(eax); 1068 AsmPush(eax);
1058 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1069 AsmInvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
1059 __ bind(&done_convert); 1070 __ bind(&done_convert);
1060 __ push(eax); 1071 AsmPush(eax);
1061 1072
1062 // Check for proxies. 1073 // Check for proxies.
1063 Label call_runtime, use_cache, fixed_array; 1074 Label call_runtime, use_cache, fixed_array;
1064 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1075 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1065 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 1076 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
1066 __ j(below_equal, &call_runtime); 1077 __ j(below_equal, &call_runtime);
1067 1078
1068 // Check cache validity in generated code. This is a fast case for 1079 // Check cache validity in generated code. This is a fast case for
1069 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1080 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1070 // guarantee cache validity, call the runtime system to check cache 1081 // guarantee cache validity, call the runtime system to check cache
1071 // validity or get the property names in a fixed array. 1082 // validity or get the property names in a fixed array.
1072 __ CheckEnumCache(&call_runtime); 1083 __ CheckEnumCache(&call_runtime);
1073 1084
1074 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 1085 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
1075 __ jmp(&use_cache, Label::kNear); 1086 __ jmp(&use_cache, Label::kNear);
1076 1087
1077 // Get the set of properties to enumerate. 1088 // Get the set of properties to enumerate.
1078 __ bind(&call_runtime); 1089 __ bind(&call_runtime);
1079 __ push(eax); 1090 AsmPush(eax);
1080 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1091 AsmCallRuntime(Runtime::kGetPropertyNamesFast, 1);
1081 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 1092 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
1082 isolate()->factory()->meta_map()); 1093 isolate()->factory()->meta_map());
1094 StackHeightWrapper top_stack_height = CurrentStackHeight();
1083 __ j(not_equal, &fixed_array); 1095 __ j(not_equal, &fixed_array);
1084 1096
1085 1097
1086 // We got a map in register eax. Get the enumeration cache from it. 1098 // We got a map in register eax. Get the enumeration cache from it.
1087 Label no_descriptors; 1099 Label no_descriptors;
1088 __ bind(&use_cache); 1100 __ bind(&use_cache);
1089 1101
1090 __ EnumLength(edx, eax); 1102 __ EnumLength(edx, eax);
1091 __ cmp(edx, Immediate(Smi::FromInt(0))); 1103 __ cmp(edx, Immediate(Smi::FromInt(0)));
1092 __ j(equal, &no_descriptors); 1104 __ j(equal, &no_descriptors);
1093 1105
1094 __ LoadInstanceDescriptors(eax, ecx); 1106 __ LoadInstanceDescriptors(eax, ecx);
1095 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheOffset)); 1107 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheOffset));
1096 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1108 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1097 1109
1098 // Set up the four remaining stack slots. 1110 // Set up the four remaining stack slots.
1099 __ push(eax); // Map. 1111 AsmPush(eax); // Map.
1100 __ push(ecx); // Enumeration cache. 1112 AsmPush(ecx); // Enumeration cache.
1101 __ push(edx); // Number of valid entries for the map in the enum cache. 1113 AsmPush(edx); // Number of valid entries for the map in the enum cache.
1102 __ push(Immediate(Smi::FromInt(0))); // Initial index. 1114 AsmPushSmi(Smi::FromInt(0)); // Initial index.
1103 __ jmp(&loop); 1115 __ jmp(&loop);
1104 1116
1105 __ bind(&no_descriptors); 1117 __ bind(&no_descriptors);
1106 __ add(esp, Immediate(kPointerSize)); 1118 SetStackHeight(top_stack_height);
1119 AsmDrop(1);
1120 StackHeightWrapper exit_stack_height = CurrentStackHeight();
1107 __ jmp(&exit); 1121 __ jmp(&exit);
1108 1122
1109 // We got a fixed array in register eax. Iterate through that. 1123 // We got a fixed array in register eax. Iterate through that.
1110 Label non_proxy; 1124 Label non_proxy;
1111 __ bind(&fixed_array); 1125 __ bind(&fixed_array);
1126 SetStackHeight(top_stack_height);
1112 1127
1113 // No need for a write barrier, we are storing a Smi in the feedback vector. 1128 // No need for a write barrier, we are storing a Smi in the feedback vector.
1114 __ LoadHeapObject(ebx, FeedbackVector()); 1129 __ LoadHeapObject(ebx, FeedbackVector());
1115 __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)), 1130 __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
1116 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate()))); 1131 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
1117 1132
1118 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check 1133 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
1119 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object 1134 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
1120 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1135 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1121 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx); 1136 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx);
1122 __ j(above, &non_proxy); 1137 __ j(above, &non_proxy);
1123 __ Move(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy 1138 __ Move(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy
1124 __ bind(&non_proxy); 1139 __ bind(&non_proxy);
1125 __ push(ebx); // Smi 1140 AsmPush(ebx); // Smi
1126 __ push(eax); // Array 1141 AsmPush(eax); // Array
1127 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 1142 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1128 __ push(eax); // Fixed array length (as smi). 1143 AsmPush(eax); // Fixed array length (as smi).
1129 __ push(Immediate(Smi::FromInt(0))); // Initial index. 1144 AsmPushSmi(Smi::FromInt(0)); // Initial index.
1130 1145
1131 // Generate code for doing the condition check. 1146 // Generate code for doing the condition check.
1147 __ bind(&loop);
1132 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1148 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1133 __ bind(&loop);
1134 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. 1149 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
1135 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. 1150 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
1136 __ j(above_equal, loop_statement.break_label()); 1151 __ j(above_equal, loop_statement.break_label());
1137 1152
1138 // Get the current entry of the array into register ebx. 1153 // Get the current entry of the array into register ebx.
1139 __ mov(ebx, Operand(esp, 2 * kPointerSize)); 1154 __ mov(ebx, Operand(esp, 2 * kPointerSize));
1140 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); 1155 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1141 1156
1142 // Get the expected map from the stack or a smi in the 1157 // Get the expected map from the stack or a smi in the
1143 // permanent slow case into register edx. 1158 // permanent slow case into register edx.
1144 __ mov(edx, Operand(esp, 3 * kPointerSize)); 1159 __ mov(edx, Operand(esp, 3 * kPointerSize));
1145 1160
1146 // Check if the expected map still matches that of the enumerable. 1161 // Check if the expected map still matches that of the enumerable.
1147 // If not, we may have to filter the key. 1162 // If not, we may have to filter the key.
1148 Label update_each; 1163 Label update_each;
1149 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1164 __ mov(ecx, Operand(esp, 4 * kPointerSize));
1150 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 1165 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1151 __ j(equal, &update_each, Label::kNear); 1166 __ j(equal, &update_each, Label::kNear);
1152 1167
1153 // For proxies, no filtering is done. 1168 // For proxies, no filtering is done.
1154 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1169 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1155 ASSERT(Smi::FromInt(0) == 0); 1170 ASSERT(Smi::FromInt(0) == 0);
1156 __ test(edx, edx); 1171 __ test(edx, edx);
1172 StackHeightWrapper update_each_stack_height = CurrentStackHeight();
1157 __ j(zero, &update_each); 1173 __ j(zero, &update_each);
1158 1174
1159 // Convert the entry to a string or null if it isn't a property 1175 // Convert the entry to a string or null if it isn't a property
1160 // anymore. If the property has been removed while iterating, we 1176 // anymore. If the property has been removed while iterating, we
1161 // just skip it. 1177 // just skip it.
1162 __ push(ecx); // Enumerable. 1178 AsmPush(ecx); // Enumerable.
1163 __ push(ebx); // Current entry. 1179 AsmPush(ebx); // Current entry.
1164 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1180 AsmInvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
1165 __ test(eax, eax); 1181 __ test(eax, eax);
1166 __ j(equal, loop_statement.continue_label()); 1182 __ j(equal, loop_statement.continue_label());
1167 __ mov(ebx, eax); 1183 __ mov(ebx, eax);
1168 1184
1169 // Update the 'each' property or variable from the possibly filtered 1185 // Update the 'each' property or variable from the possibly filtered
1170 // entry in register ebx. 1186 // entry in register ebx.
1171 __ bind(&update_each); 1187 __ bind(&update_each);
1188 USE(update_each_stack_height);
1189 ASSERT(update_each_stack_height.get() == stack_height_.get());
1172 __ mov(result_register(), ebx); 1190 __ mov(result_register(), ebx);
1173 // Perform the assignment as if via '='. 1191 // Perform the assignment as if via '='.
1174 { EffectContext context(this); 1192 { EffectContext context(this);
1175 EmitAssignment(stmt->each()); 1193 EmitAssignment(stmt->each());
1176 } 1194 }
1177 1195
1178 // Generate code for the body of the loop. 1196 // Generate code for the body of the loop.
1179 Visit(stmt->body()); 1197 Visit(stmt->body());
1180 1198
1181 // Generate code for going to the next element by incrementing the 1199 // Generate code for going to the next element by incrementing the
1182 // index (smi) stored on top of the stack. 1200 // index (smi) stored on top of the stack.
1183 __ bind(loop_statement.continue_label()); 1201 __ bind(loop_statement.continue_label());
1184 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 1202 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1185 1203
1186 EmitBackEdgeBookkeeping(stmt, &loop); 1204 EmitBackEdgeBookkeeping(stmt, &loop);
1187 __ jmp(&loop); 1205 __ jmp(&loop);
1188 1206
1189 // Remove the pointers stored on the stack. 1207 // Remove the pointers stored on the stack.
1190 __ bind(loop_statement.break_label()); 1208 __ bind(loop_statement.break_label());
1191 __ add(esp, Immediate(5 * kPointerSize)); 1209 AsmDrop(5);
1192 1210
1193 // Exit and decrement the loop depth. 1211 // Exit and decrement the loop depth.
1212 __ bind(&exit);
1194 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1213 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1195 __ bind(&exit);
1196 decrement_loop_depth(); 1214 decrement_loop_depth();
1215 SetStackHeight(exit_stack_height);
1197 } 1216 }
1198 1217
1199 1218
1200 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1219 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1201 Comment cmnt(masm_, "[ ForOfStatement"); 1220 Comment cmnt(masm_, "[ ForOfStatement");
1202 SetStatementPosition(stmt); 1221 SetStatementPosition(stmt);
1203 1222
1204 Iteration loop_statement(this, stmt); 1223 Iteration loop_statement(this, stmt);
1205 increment_loop_depth(); 1224 increment_loop_depth();
1206 1225
1207 // var iterator = iterable[@@iterator]() 1226 // var iterator = iterable[@@iterator]()
1208 VisitForAccumulatorValue(stmt->assign_iterator()); 1227 VisitForAccumulatorValue(stmt->assign_iterator());
1209 1228
1210 // As with for-in, skip the loop if the iterator is null or undefined. 1229 // As with for-in, skip the loop if the iterator is null or undefined.
1211 __ CompareRoot(eax, Heap::kUndefinedValueRootIndex); 1230 __ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
1212 __ j(equal, loop_statement.break_label()); 1231 __ j(equal, loop_statement.break_label());
1213 __ CompareRoot(eax, Heap::kNullValueRootIndex); 1232 __ CompareRoot(eax, Heap::kNullValueRootIndex);
1214 __ j(equal, loop_statement.break_label()); 1233 __ j(equal, loop_statement.break_label());
1215 1234
1216 // Convert the iterator to a JS object. 1235 // Convert the iterator to a JS object.
1217 Label convert, done_convert; 1236 Label convert, done_convert;
1218 __ JumpIfSmi(eax, &convert); 1237 __ JumpIfSmi(eax, &convert);
1219 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1238 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1220 __ j(above_equal, &done_convert); 1239 __ j(above_equal, &done_convert);
1221 __ bind(&convert); 1240 __ bind(&convert);
1222 __ push(eax); 1241 AsmPush(eax);
1223 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1242 AsmInvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
1224 __ bind(&done_convert); 1243 __ bind(&done_convert);
1225 1244
1226 // Loop entry. 1245 // Loop entry.
1227 __ bind(loop_statement.continue_label()); 1246 __ bind(loop_statement.continue_label());
1228 1247
1229 // result = iterator.next() 1248 // result = iterator.next()
1230 VisitForEffect(stmt->next_result()); 1249 VisitForEffect(stmt->next_result());
1231 1250
1232 // if (result.done) break; 1251 // if (result.done) break;
1233 Label result_not_done; 1252 Label result_not_done;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 !FLAG_prepare_always_opt && 1286 !FLAG_prepare_always_opt &&
1268 !pretenure && 1287 !pretenure &&
1269 scope()->is_function_scope() && 1288 scope()->is_function_scope() &&
1270 info->num_literals() == 0) { 1289 info->num_literals() == 0) {
1271 FastNewClosureStub stub(isolate(), 1290 FastNewClosureStub stub(isolate(),
1272 info->strict_mode(), 1291 info->strict_mode(),
1273 info->is_generator()); 1292 info->is_generator());
1274 __ mov(ebx, Immediate(info)); 1293 __ mov(ebx, Immediate(info));
1275 __ CallStub(&stub); 1294 __ CallStub(&stub);
1276 } else { 1295 } else {
1277 __ push(esi); 1296 AsmPush(esi);
1278 __ push(Immediate(info)); 1297 AsmPushHandle(info);
1279 __ push(Immediate(pretenure 1298 AsmPushHandle(pretenure
1280 ? isolate()->factory()->true_value() 1299 ? isolate()->factory()->true_value()
1281 : isolate()->factory()->false_value())); 1300 : isolate()->factory()->false_value());
1282 __ CallRuntime(Runtime::kHiddenNewClosure, 3); 1301 AsmCallRuntime(Runtime::kHiddenNewClosure, 3);
1283 } 1302 }
1284 context()->Plug(eax); 1303 context()->Plug(eax);
1285 } 1304 }
1286 1305
1287 1306
1288 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 1307 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1289 Comment cmnt(masm_, "[ VariableProxy"); 1308 Comment cmnt(masm_, "[ VariableProxy");
1290 EmitVariableLoad(expr); 1309 EmitVariableLoad(expr);
1291 } 1310 }
1292 1311
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 } else if (var->mode() == DYNAMIC_LOCAL) { 1415 } else if (var->mode() == DYNAMIC_LOCAL) {
1397 Variable* local = var->local_if_not_shadowed(); 1416 Variable* local = var->local_if_not_shadowed();
1398 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); 1417 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
1399 if (local->mode() == LET || local->mode() == CONST || 1418 if (local->mode() == LET || local->mode() == CONST ||
1400 local->mode() == CONST_LEGACY) { 1419 local->mode() == CONST_LEGACY) {
1401 __ cmp(eax, isolate()->factory()->the_hole_value()); 1420 __ cmp(eax, isolate()->factory()->the_hole_value());
1402 __ j(not_equal, done); 1421 __ j(not_equal, done);
1403 if (local->mode() == CONST_LEGACY) { 1422 if (local->mode() == CONST_LEGACY) {
1404 __ mov(eax, isolate()->factory()->undefined_value()); 1423 __ mov(eax, isolate()->factory()->undefined_value());
1405 } else { // LET || CONST 1424 } else { // LET || CONST
1406 __ push(Immediate(var->name())); 1425 AsmPushHandle(var->name());
1407 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); 1426 AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1408 } 1427 }
1409 } 1428 }
1410 __ jmp(done); 1429 __ jmp(done);
1411 } 1430 }
1412 } 1431 }
1413 1432
1414 1433
1415 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1434 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1416 // Record position before possible IC call. 1435 // Record position before possible IC call.
1417 SetSourcePosition(proxy->position()); 1436 SetSourcePosition(proxy->position());
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 1492
1474 if (!skip_init_check) { 1493 if (!skip_init_check) {
1475 // Let and const need a read barrier. 1494 // Let and const need a read barrier.
1476 Label done; 1495 Label done;
1477 GetVar(eax, var); 1496 GetVar(eax, var);
1478 __ cmp(eax, isolate()->factory()->the_hole_value()); 1497 __ cmp(eax, isolate()->factory()->the_hole_value());
1479 __ j(not_equal, &done, Label::kNear); 1498 __ j(not_equal, &done, Label::kNear);
1480 if (var->mode() == LET || var->mode() == CONST) { 1499 if (var->mode() == LET || var->mode() == CONST) {
1481 // Throw a reference error when using an uninitialized let/const 1500 // Throw a reference error when using an uninitialized let/const
1482 // binding in harmony mode. 1501 // binding in harmony mode.
1483 __ push(Immediate(var->name())); 1502 AsmPushHandle(var->name());
1484 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); 1503 AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1485 } else { 1504 } else {
1486 // Uninitalized const bindings outside of harmony mode are unholed. 1505 // Uninitalized const bindings outside of harmony mode are unholed.
1487 ASSERT(var->mode() == CONST_LEGACY); 1506 ASSERT(var->mode() == CONST_LEGACY);
1488 __ mov(eax, isolate()->factory()->undefined_value()); 1507 __ mov(eax, isolate()->factory()->undefined_value());
1489 } 1508 }
1490 __ bind(&done); 1509 __ bind(&done);
1491 context()->Plug(eax); 1510 context()->Plug(eax);
1492 break; 1511 break;
1493 } 1512 }
1494 } 1513 }
1495 context()->Plug(var); 1514 context()->Plug(var);
1496 break; 1515 break;
1497 } 1516 }
1498 1517
1499 case Variable::LOOKUP: { 1518 case Variable::LOOKUP: {
1500 Comment cmnt(masm_, "[ Lookup variable"); 1519 Comment cmnt(masm_, "[ Lookup variable");
1501 Label done, slow; 1520 Label done, slow;
1502 // Generate code for loading from variables potentially shadowed 1521 // Generate code for loading from variables potentially shadowed
1503 // by eval-introduced variables. 1522 // by eval-introduced variables.
1504 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1523 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1505 __ bind(&slow); 1524 __ bind(&slow);
1506 __ push(esi); // Context. 1525 AsmPush(esi); // Context.
1507 __ push(Immediate(var->name())); 1526 AsmPushHandle(var->name());
1508 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); 1527 AsmCallRuntime(Runtime::kHiddenLoadContextSlot, 2);
1509 __ bind(&done); 1528 __ bind(&done);
1510 context()->Plug(eax); 1529 context()->Plug(eax);
1511 break; 1530 break;
1512 } 1531 }
1513 } 1532 }
1514 } 1533 }
1515 1534
1516 1535
1517 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1536 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1518 Comment cmnt(masm_, "[ RegExpLiteral"); 1537 Comment cmnt(masm_, "[ RegExpLiteral");
1519 Label materialized; 1538 Label materialized;
1520 // Registers will be used as follows: 1539 // Registers will be used as follows:
1521 // edi = JS function. 1540 // edi = JS function.
1522 // ecx = literals array. 1541 // ecx = literals array.
1523 // ebx = regexp literal. 1542 // ebx = regexp literal.
1524 // eax = regexp literal clone. 1543 // eax = regexp literal clone.
1525 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1544 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1526 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 1545 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
1527 int literal_offset = 1546 int literal_offset =
1528 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1547 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1529 __ mov(ebx, FieldOperand(ecx, literal_offset)); 1548 __ mov(ebx, FieldOperand(ecx, literal_offset));
1530 __ cmp(ebx, isolate()->factory()->undefined_value()); 1549 __ cmp(ebx, isolate()->factory()->undefined_value());
1531 __ j(not_equal, &materialized, Label::kNear); 1550 __ j(not_equal, &materialized, Label::kNear);
1532 1551
1533 // Create regexp literal using runtime function 1552 // Create regexp literal using runtime function
1534 // Result will be in eax. 1553 // Result will be in eax.
1535 __ push(ecx); 1554 AsmPush(ecx);
1536 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1555 AsmPushSmi(Smi::FromInt(expr->literal_index()));
1537 __ push(Immediate(expr->pattern())); 1556 AsmPushHandle(expr->pattern());
1538 __ push(Immediate(expr->flags())); 1557 AsmPushHandle(expr->flags());
1539 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); 1558 AsmCallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
1540 __ mov(ebx, eax); 1559 __ mov(ebx, eax);
1541 1560
1542 __ bind(&materialized); 1561 __ bind(&materialized);
1543 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1562 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1544 Label allocated, runtime_allocate; 1563 Label allocated, runtime_allocate;
1545 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 1564 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
1546 __ jmp(&allocated); 1565 __ jmp(&allocated);
1547 1566
1548 __ bind(&runtime_allocate); 1567 __ bind(&runtime_allocate);
1549 __ push(ebx); 1568 AsmPush(ebx);
1550 __ push(Immediate(Smi::FromInt(size))); 1569 AsmPushSmi(Smi::FromInt(size));
1551 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); 1570 AsmCallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
1552 __ pop(ebx); 1571 AsmPop(ebx);
1553 1572
1554 __ bind(&allocated); 1573 __ bind(&allocated);
1555 // Copy the content into the newly allocated memory. 1574 // Copy the content into the newly allocated memory.
1556 // (Unroll copy loop once for better throughput). 1575 // (Unroll copy loop once for better throughput).
1557 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1576 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1558 __ mov(edx, FieldOperand(ebx, i)); 1577 __ mov(edx, FieldOperand(ebx, i));
1559 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); 1578 __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
1560 __ mov(FieldOperand(eax, i), edx); 1579 __ mov(FieldOperand(eax, i), edx);
1561 __ mov(FieldOperand(eax, i + kPointerSize), ecx); 1580 __ mov(FieldOperand(eax, i + kPointerSize), ecx);
1562 } 1581 }
1563 if ((size % (2 * kPointerSize)) != 0) { 1582 if ((size % (2 * kPointerSize)) != 0) {
1564 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); 1583 __ mov(edx, FieldOperand(ebx, size - kPointerSize));
1565 __ mov(FieldOperand(eax, size - kPointerSize), edx); 1584 __ mov(FieldOperand(eax, size - kPointerSize), edx);
1566 } 1585 }
1567 context()->Plug(eax); 1586 context()->Plug(eax);
1568 } 1587 }
1569 1588
1570 1589
1571 void FullCodeGenerator::EmitAccessor(Expression* expression) { 1590 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1572 if (expression == NULL) { 1591 if (expression == NULL) {
1573 __ push(Immediate(isolate()->factory()->null_value())); 1592 AsmPushHandle(isolate()->factory()->null_value());
1574 } else { 1593 } else {
1575 VisitForStackValue(expression); 1594 VisitForStackValue(expression);
1576 } 1595 }
1577 } 1596 }
1578 1597
1579 1598
1580 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1599 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1581 Comment cmnt(masm_, "[ ObjectLiteral"); 1600 Comment cmnt(masm_, "[ ObjectLiteral");
1582 1601
1583 expr->BuildConstantProperties(isolate()); 1602 expr->BuildConstantProperties(isolate());
1584 Handle<FixedArray> constant_properties = expr->constant_properties(); 1603 Handle<FixedArray> constant_properties = expr->constant_properties();
1585 int flags = expr->fast_elements() 1604 int flags = expr->fast_elements()
1586 ? ObjectLiteral::kFastElements 1605 ? ObjectLiteral::kFastElements
1587 : ObjectLiteral::kNoFlags; 1606 : ObjectLiteral::kNoFlags;
1588 flags |= expr->has_function() 1607 flags |= expr->has_function()
1589 ? ObjectLiteral::kHasFunction 1608 ? ObjectLiteral::kHasFunction
1590 : ObjectLiteral::kNoFlags; 1609 : ObjectLiteral::kNoFlags;
1591 int properties_count = constant_properties->length() / 2; 1610 int properties_count = constant_properties->length() / 2;
1592 if (expr->may_store_doubles() || expr->depth() > 1 || 1611 if (expr->may_store_doubles() || expr->depth() > 1 ||
1593 masm()->serializer_enabled() || 1612 masm()->serializer_enabled() ||
1594 flags != ObjectLiteral::kFastElements || 1613 flags != ObjectLiteral::kFastElements ||
1595 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1614 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1596 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1615 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1597 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); 1616 AsmPush(FieldOperand(edi, JSFunction::kLiteralsOffset));
1598 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1617 AsmPushSmi(Smi::FromInt(expr->literal_index()));
1599 __ push(Immediate(constant_properties)); 1618 AsmPushHandle(constant_properties);
1600 __ push(Immediate(Smi::FromInt(flags))); 1619 AsmPushSmi(Smi::FromInt(flags));
1601 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); 1620 AsmCallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
1602 } else { 1621 } else {
1603 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1622 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1604 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset)); 1623 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset));
1605 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); 1624 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1606 __ mov(ecx, Immediate(constant_properties)); 1625 __ mov(ecx, Immediate(constant_properties));
1607 __ mov(edx, Immediate(Smi::FromInt(flags))); 1626 __ mov(edx, Immediate(Smi::FromInt(flags)));
1608 FastCloneShallowObjectStub stub(isolate(), properties_count); 1627 FastCloneShallowObjectStub stub(isolate(), properties_count);
1609 __ CallStub(&stub); 1628 __ CallStub(&stub);
1610 } 1629 }
1611 1630
1612 // If result_saved is true the result is on top of the stack. If 1631 // If result_saved is true the result is on top of the stack. If
1613 // result_saved is false the result is in eax. 1632 // result_saved is false the result is in eax.
1614 bool result_saved = false; 1633 bool result_saved = false;
1615 1634
1616 // Mark all computed expressions that are bound to a key that 1635 // Mark all computed expressions that are bound to a key that
1617 // is shadowed by a later occurrence of the same key. For the 1636 // is shadowed by a later occurrence of the same key. For the
1618 // marked expressions, no store code is emitted. 1637 // marked expressions, no store code is emitted.
1619 expr->CalculateEmitStore(zone()); 1638 expr->CalculateEmitStore(zone());
1620 1639
1621 AccessorTable accessor_table(zone()); 1640 AccessorTable accessor_table(zone());
1622 for (int i = 0; i < expr->properties()->length(); i++) { 1641 for (int i = 0; i < expr->properties()->length(); i++) {
1623 ObjectLiteral::Property* property = expr->properties()->at(i); 1642 ObjectLiteral::Property* property = expr->properties()->at(i);
1624 if (property->IsCompileTimeValue()) continue; 1643 if (property->IsCompileTimeValue()) continue;
1625 1644
1626 Literal* key = property->key(); 1645 Literal* key = property->key();
1627 Expression* value = property->value(); 1646 Expression* value = property->value();
1628 if (!result_saved) { 1647 if (!result_saved) {
1629 __ push(eax); // Save result on the stack 1648 AsmPush(eax); // Save result on the stack
1630 result_saved = true; 1649 result_saved = true;
1631 } 1650 }
1632 switch (property->kind()) { 1651 switch (property->kind()) {
1633 case ObjectLiteral::Property::CONSTANT: 1652 case ObjectLiteral::Property::CONSTANT:
1634 UNREACHABLE(); 1653 UNREACHABLE();
1635 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1654 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1636 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1655 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1637 // Fall through. 1656 // Fall through.
1638 case ObjectLiteral::Property::COMPUTED: 1657 case ObjectLiteral::Property::COMPUTED:
1639 if (key->value()->IsInternalizedString()) { 1658 if (key->value()->IsInternalizedString()) {
1640 if (property->emit_store()) { 1659 if (property->emit_store()) {
1641 VisitForAccumulatorValue(value); 1660 VisitForAccumulatorValue(value);
1642 __ mov(ecx, Immediate(key->value())); 1661 __ mov(ecx, Immediate(key->value()));
1643 __ mov(edx, Operand(esp, 0)); 1662 __ mov(edx, Operand(esp, 0));
1644 CallStoreIC(key->LiteralFeedbackId()); 1663 CallStoreIC(key->LiteralFeedbackId());
1645 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1664 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1646 } else { 1665 } else {
1647 VisitForEffect(value); 1666 VisitForEffect(value);
1648 } 1667 }
1649 break; 1668 break;
1650 } 1669 }
1651 __ push(Operand(esp, 0)); // Duplicate receiver. 1670 AsmPush(Operand(esp, 0)); // Duplicate receiver.
1652 VisitForStackValue(key); 1671 VisitForStackValue(key);
1653 VisitForStackValue(value); 1672 VisitForStackValue(value);
1654 if (property->emit_store()) { 1673 if (property->emit_store()) {
1655 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes 1674 AsmPushSmi(Smi::FromInt(NONE)); // PropertyAttributes
1656 __ CallRuntime(Runtime::kSetProperty, 4); 1675 AsmCallRuntime(Runtime::kSetProperty, 4);
1657 } else { 1676 } else {
1658 __ Drop(3); 1677 AsmDrop(3);
1659 } 1678 }
1660 break; 1679 break;
1661 case ObjectLiteral::Property::PROTOTYPE: 1680 case ObjectLiteral::Property::PROTOTYPE:
1662 __ push(Operand(esp, 0)); // Duplicate receiver. 1681 AsmPush(Operand(esp, 0)); // Duplicate receiver.
1663 VisitForStackValue(value); 1682 VisitForStackValue(value);
1664 if (property->emit_store()) { 1683 if (property->emit_store()) {
1665 __ CallRuntime(Runtime::kSetPrototype, 2); 1684 AsmCallRuntime(Runtime::kSetPrototype, 2);
1666 } else { 1685 } else {
1667 __ Drop(2); 1686 AsmDrop(2);
1668 } 1687 }
1669 break; 1688 break;
1670 case ObjectLiteral::Property::GETTER: 1689 case ObjectLiteral::Property::GETTER:
1671 accessor_table.lookup(key)->second->getter = value; 1690 accessor_table.lookup(key)->second->getter = value;
1672 break; 1691 break;
1673 case ObjectLiteral::Property::SETTER: 1692 case ObjectLiteral::Property::SETTER:
1674 accessor_table.lookup(key)->second->setter = value; 1693 accessor_table.lookup(key)->second->setter = value;
1675 break; 1694 break;
1676 } 1695 }
1677 } 1696 }
1678 1697
1698
1679 // Emit code to define accessors, using only a single call to the runtime for 1699 // Emit code to define accessors, using only a single call to the runtime for
1680 // each pair of corresponding getters and setters. 1700 // each pair of corresponding getters and setters.
1681 for (AccessorTable::Iterator it = accessor_table.begin(); 1701 for (AccessorTable::Iterator it = accessor_table.begin();
1682 it != accessor_table.end(); 1702 it != accessor_table.end();
1683 ++it) { 1703 ++it) {
1684 __ push(Operand(esp, 0)); // Duplicate receiver. 1704 AsmPush(Operand(esp, 0)); // Duplicate receiver.
1685 VisitForStackValue(it->first); 1705 VisitForStackValue(it->first);
1686 EmitAccessor(it->second->getter); 1706 EmitAccessor(it->second->getter);
1687 EmitAccessor(it->second->setter); 1707 EmitAccessor(it->second->setter);
1688 __ push(Immediate(Smi::FromInt(NONE))); 1708 AsmPushSmi(Smi::FromInt(NONE));
1689 __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5); 1709 AsmCallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
1690 } 1710 }
1691 1711
1692 if (expr->has_function()) { 1712 if (expr->has_function()) {
1693 ASSERT(result_saved); 1713 ASSERT(result_saved);
1694 __ push(Operand(esp, 0)); 1714 AsmPush(Operand(esp, 0));
1695 __ CallRuntime(Runtime::kToFastProperties, 1); 1715 AsmCallRuntime(Runtime::kToFastProperties, 1);
1696 } 1716 }
1697 1717
1698 if (result_saved) { 1718 if (result_saved) {
1699 context()->PlugTOS(); 1719 context()->PlugTOS();
1700 } else { 1720 } else {
1701 context()->Plug(eax); 1721 context()->Plug(eax);
1702 } 1722 }
1703 } 1723 }
1704 1724
1705 1725
(...skipping 18 matching lines...) Expand all
1724 1744
1725 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1745 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1726 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { 1746 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1727 // If the only customer of allocation sites is transitioning, then 1747 // If the only customer of allocation sites is transitioning, then
1728 // we can turn it off if we don't have anywhere else to transition to. 1748 // we can turn it off if we don't have anywhere else to transition to.
1729 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1749 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1730 } 1750 }
1731 1751
1732 if (expr->depth() > 1) { 1752 if (expr->depth() > 1) {
1733 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1753 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1734 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 1754 AsmPush(FieldOperand(ebx, JSFunction::kLiteralsOffset));
1735 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1755 AsmPushSmi(Smi::FromInt(expr->literal_index()));
1736 __ push(Immediate(constant_elements)); 1756 AsmPushHandle(constant_elements);
1737 __ push(Immediate(Smi::FromInt(flags))); 1757 AsmPushSmi(Smi::FromInt(flags));
1738 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); 1758 AsmCallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
1739 } else { 1759 } else {
1740 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1760 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1741 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset)); 1761 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
1742 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); 1762 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1743 __ mov(ecx, Immediate(constant_elements)); 1763 __ mov(ecx, Immediate(constant_elements));
1744 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1764 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1745 __ CallStub(&stub); 1765 __ CallStub(&stub);
1746 } 1766 }
1747 1767
1748 bool result_saved = false; // Is the result saved to the stack? 1768 bool result_saved = false; // Is the result saved to the stack?
1749 1769
1750 // Emit code to evaluate all the non-constant subexpressions and to store 1770 // Emit code to evaluate all the non-constant subexpressions and to store
1751 // them into the newly cloned array. 1771 // them into the newly cloned array.
1752 for (int i = 0; i < length; i++) { 1772 for (int i = 0; i < length; i++) {
1753 Expression* subexpr = subexprs->at(i); 1773 Expression* subexpr = subexprs->at(i);
1754 // If the subexpression is a literal or a simple materialized literal it 1774 // If the subexpression is a literal or a simple materialized literal it
1755 // is already set in the cloned array. 1775 // is already set in the cloned array.
1756 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1776 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1757 1777
1758 if (!result_saved) { 1778 if (!result_saved) {
1759 __ push(eax); // array literal. 1779 AsmPush(eax); // array literal.
1760 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1780 AsmPushSmi(Smi::FromInt(expr->literal_index()));
1761 result_saved = true; 1781 result_saved = true;
1762 } 1782 }
1763 VisitForAccumulatorValue(subexpr); 1783 VisitForAccumulatorValue(subexpr);
1764 1784
1765 if (IsFastObjectElementsKind(constant_elements_kind)) { 1785 if (IsFastObjectElementsKind(constant_elements_kind)) {
1766 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they 1786 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1767 // cannot transition and don't need to call the runtime stub. 1787 // cannot transition and don't need to call the runtime stub.
1768 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1788 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1769 __ mov(ebx, Operand(esp, kPointerSize)); // Copy of array literal. 1789 __ mov(ebx, Operand(esp, kPointerSize)); // Copy of array literal.
1770 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 1790 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
1771 // Store the subexpression value in the array's elements. 1791 // Store the subexpression value in the array's elements.
1772 __ mov(FieldOperand(ebx, offset), result_register()); 1792 __ mov(FieldOperand(ebx, offset), result_register());
1773 // Update the write barrier for the array store. 1793 // Update the write barrier for the array store.
1774 __ RecordWriteField(ebx, offset, result_register(), ecx, 1794 __ RecordWriteField(ebx, offset, result_register(), ecx,
1775 kDontSaveFPRegs, 1795 kDontSaveFPRegs,
1776 EMIT_REMEMBERED_SET, 1796 EMIT_REMEMBERED_SET,
1777 INLINE_SMI_CHECK); 1797 INLINE_SMI_CHECK);
1778 } else { 1798 } else {
1779 // Store the subexpression value in the array's elements. 1799 // Store the subexpression value in the array's elements.
1780 __ mov(ecx, Immediate(Smi::FromInt(i))); 1800 __ mov(ecx, Immediate(Smi::FromInt(i)));
1781 StoreArrayLiteralElementStub stub(isolate()); 1801 StoreArrayLiteralElementStub stub(isolate());
1782 __ CallStub(&stub); 1802 __ CallStub(&stub);
1783 } 1803 }
1784 1804
1785 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1805 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1786 } 1806 }
1787 1807
1788 if (result_saved) { 1808 if (result_saved) {
1789 __ add(esp, Immediate(kPointerSize)); // literal index 1809 AsmDrop(1);
1790 context()->PlugTOS(); 1810 context()->PlugTOS();
1791 } else { 1811 } else {
1792 context()->Plug(eax); 1812 context()->Plug(eax);
1793 } 1813 }
1794 } 1814 }
1795 1815
1796 1816
1797 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1817 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1798 ASSERT(expr->target()->IsValidReferenceExpression()); 1818 ASSERT(expr->target()->IsValidReferenceExpression());
1799 1819
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 PrepareForBailoutForId(property->LoadId(), TOS_REG); 1873 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1854 break; 1874 break;
1855 case KEYED_PROPERTY: 1875 case KEYED_PROPERTY:
1856 EmitKeyedPropertyLoad(property); 1876 EmitKeyedPropertyLoad(property);
1857 PrepareForBailoutForId(property->LoadId(), TOS_REG); 1877 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1858 break; 1878 break;
1859 } 1879 }
1860 } 1880 }
1861 1881
1862 Token::Value op = expr->binary_op(); 1882 Token::Value op = expr->binary_op();
1863 __ push(eax); // Left operand goes on the stack. 1883 AsmPush(eax); // Left operand goes on the stack.
1864 VisitForAccumulatorValue(expr->value()); 1884 VisitForAccumulatorValue(expr->value());
1865 1885
1866 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1886 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1867 ? OVERWRITE_RIGHT 1887 ? OVERWRITE_RIGHT
1868 : NO_OVERWRITE; 1888 : NO_OVERWRITE;
1869 SetSourcePosition(expr->position() + 1); 1889 SetSourcePosition(expr->position() + 1);
1870 if (ShouldInlineSmiCase(op)) { 1890 if (ShouldInlineSmiCase(op)) {
1871 EmitInlineSmiBinaryOp(expr->binary_operation(), 1891 EmitInlineSmiBinaryOp(expr->binary_operation(),
1872 op, 1892 op,
1873 mode, 1893 mode,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 void FullCodeGenerator::VisitYield(Yield* expr) { 1927 void FullCodeGenerator::VisitYield(Yield* expr) {
1908 Comment cmnt(masm_, "[ Yield"); 1928 Comment cmnt(masm_, "[ Yield");
1909 // Evaluate yielded value first; the initial iterator definition depends on 1929 // Evaluate yielded value first; the initial iterator definition depends on
1910 // this. It stays on the stack while we update the iterator. 1930 // this. It stays on the stack while we update the iterator.
1911 VisitForStackValue(expr->expression()); 1931 VisitForStackValue(expr->expression());
1912 1932
1913 switch (expr->yield_kind()) { 1933 switch (expr->yield_kind()) {
1914 case Yield::SUSPEND: 1934 case Yield::SUSPEND:
1915 // Pop value from top-of-stack slot; box result into result register. 1935 // Pop value from top-of-stack slot; box result into result register.
1916 EmitCreateIteratorResult(false); 1936 EmitCreateIteratorResult(false);
1917 __ push(result_register()); 1937 AsmPush(result_register());
1918 // Fall through. 1938 // Fall through.
1919 case Yield::INITIAL: { 1939 case Yield::INITIAL: {
1920 Label suspend, continuation, post_runtime, resume; 1940 Label suspend, continuation, post_runtime, resume;
1921 1941
1922 __ jmp(&suspend); 1942 __ jmp(&suspend);
1923 1943
1924 __ bind(&continuation); 1944 __ bind(&continuation);
1925 __ jmp(&resume); 1945 __ jmp(&resume);
1926 1946
1927 __ bind(&suspend); 1947 __ bind(&suspend);
1928 VisitForAccumulatorValue(expr->generator_object()); 1948 VisitForAccumulatorValue(expr->generator_object());
1929 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 1949 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1930 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), 1950 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
1931 Immediate(Smi::FromInt(continuation.pos()))); 1951 Immediate(Smi::FromInt(continuation.pos())));
1932 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); 1952 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
1933 __ mov(ecx, esi); 1953 __ mov(ecx, esi);
1934 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, 1954 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
1935 kDontSaveFPRegs); 1955 kDontSaveFPRegs);
1936 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); 1956 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
1937 __ cmp(esp, ebx); 1957 __ cmp(esp, ebx);
1938 __ j(equal, &post_runtime); 1958 __ j(equal, &post_runtime);
1939 __ push(eax); // generator object 1959 AsmPush(eax); // generator object
1940 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); 1960 AsmCallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
1941 __ mov(context_register(), 1961 __ mov(context_register(),
1942 Operand(ebp, StandardFrameConstants::kContextOffset)); 1962 Operand(ebp, StandardFrameConstants::kContextOffset));
1943 __ bind(&post_runtime); 1963 __ bind(&post_runtime);
1944 __ pop(result_register()); 1964 AsmPop(result_register());
1945 EmitReturnSequence(); 1965 EmitReturnSequence();
1946 1966
1947 __ bind(&resume); 1967 __ bind(&resume);
1948 context()->Plug(result_register()); 1968 context()->Plug(result_register());
1949 break; 1969 break;
1950 } 1970 }
1951 1971
1952 case Yield::FINAL: { 1972 case Yield::FINAL: {
1953 VisitForAccumulatorValue(expr->generator_object()); 1973 VisitForAccumulatorValue(expr->generator_object());
1954 __ mov(FieldOperand(result_register(), 1974 __ mov(FieldOperand(result_register(),
1955 JSGeneratorObject::kContinuationOffset), 1975 JSGeneratorObject::kContinuationOffset),
1956 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 1976 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
1957 // Pop value from top-of-stack slot, box result into result register. 1977 // Pop value from top-of-stack slot, box result into result register.
1958 EmitCreateIteratorResult(true); 1978 EmitCreateIteratorResult(true);
1979 StackHeightWrapper final_stack_height = CurrentStackHeight();
1959 EmitUnwindBeforeReturn(); 1980 EmitUnwindBeforeReturn();
1960 EmitReturnSequence(); 1981 EmitReturnSequence();
1982 SetStackHeight(final_stack_height);
1961 break; 1983 break;
1962 } 1984 }
1963 1985
1964 case Yield::DELEGATING: { 1986 case Yield::DELEGATING: {
1965 VisitForStackValue(expr->generator_object()); 1987 VisitForStackValue(expr->generator_object());
1966 1988
1967 // Initial stack layout is as follows: 1989 // Initial stack layout is as follows:
1968 // [sp + 1 * kPointerSize] iter 1990 // [sp + 1 * kPointerSize] iter
1969 // [sp + 0 * kPointerSize] g 1991 // [sp + 0 * kPointerSize] g
1970 1992
1971 Label l_catch, l_try, l_suspend, l_continuation, l_resume; 1993 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
1972 Label l_next, l_call, l_loop; 1994 Label l_next, l_call, l_loop;
1973 // Initial send value is undefined. 1995 // Initial send value is undefined.
1974 __ mov(eax, isolate()->factory()->undefined_value()); 1996 __ mov(eax, isolate()->factory()->undefined_value());
1997 StackHeightWrapper next_stack_height = CurrentStackHeight();
1975 __ jmp(&l_next); 1998 __ jmp(&l_next);
1976 1999
1977 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2000 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
1978 __ bind(&l_catch); 2001 __ bind(&l_catch);
1979 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2002 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
1980 __ mov(ecx, isolate()->factory()->throw_string()); // "throw" 2003 __ mov(ecx, isolate()->factory()->throw_string()); // "throw"
1981 __ push(ecx); // "throw" 2004 AsmPush(ecx); // "throw"
1982 __ push(Operand(esp, 2 * kPointerSize)); // iter 2005 AsmPush(Operand(esp, 2 * kPointerSize)); // iter
1983 __ push(eax); // exception 2006 AsmPush(eax); // exception
1984 __ jmp(&l_call); 2007 __ jmp(&l_call);
1985 2008
1986 // try { received = %yield result } 2009 // try { received = %yield result }
1987 // Shuffle the received result above a try handler and yield it without 2010 // Shuffle the received result above a try handler and yield it without
1988 // re-boxing. 2011 // re-boxing.
1989 __ bind(&l_try); 2012 __ bind(&l_try);
1990 __ pop(eax); // result 2013 SetStackHeight(next_stack_height);
1991 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2014 UpdateStackHeight(1);
2015 AsmPop(eax); // result
2016 AsmPushTryHandler(StackHandler::CATCH, expr->index());
1992 const int handler_size = StackHandlerConstants::kSize; 2017 const int handler_size = StackHandlerConstants::kSize;
1993 __ push(eax); // result 2018 AsmPush(eax); // result
1994 __ jmp(&l_suspend); 2019 __ jmp(&l_suspend);
1995 __ bind(&l_continuation); 2020 __ bind(&l_continuation);
1996 __ jmp(&l_resume); 2021 __ jmp(&l_resume);
1997 __ bind(&l_suspend); 2022 __ bind(&l_suspend);
1998 const int generator_object_depth = kPointerSize + handler_size; 2023 const int generator_object_depth = kPointerSize + handler_size;
1999 __ mov(eax, Operand(esp, generator_object_depth)); 2024 __ mov(eax, Operand(esp, generator_object_depth));
2000 __ push(eax); // g 2025 AsmPush(eax); // g
2001 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2026 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2002 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), 2027 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
2003 Immediate(Smi::FromInt(l_continuation.pos()))); 2028 Immediate(Smi::FromInt(l_continuation.pos())));
2004 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); 2029 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
2005 __ mov(ecx, esi); 2030 __ mov(ecx, esi);
2006 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, 2031 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
2007 kDontSaveFPRegs); 2032 kDontSaveFPRegs);
2008 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); 2033 AsmCallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
2009 __ mov(context_register(), 2034 __ mov(context_register(),
2010 Operand(ebp, StandardFrameConstants::kContextOffset)); 2035 Operand(ebp, StandardFrameConstants::kContextOffset));
2011 __ pop(eax); // result 2036 AsmPop(eax); // result
2012 EmitReturnSequence(); 2037 EmitReturnSequence();
2013 __ bind(&l_resume); // received in eax 2038 __ bind(&l_resume); // received in eax
2014 __ PopTryHandler(); 2039 AsmPopTryHandler();
2015 2040
2016 // receiver = iter; f = iter.next; arg = received; 2041 // receiver = iter; f = iter.next; arg = received;
2017 __ bind(&l_next); 2042 __ bind(&l_next);
2043 SetStackHeight(next_stack_height);
2018 __ mov(ecx, isolate()->factory()->next_string()); // "next" 2044 __ mov(ecx, isolate()->factory()->next_string()); // "next"
2019 __ push(ecx); 2045 AsmPush(ecx);
2020 __ push(Operand(esp, 2 * kPointerSize)); // iter 2046 AsmPush(Operand(esp, 2 * kPointerSize)); // iter
2021 __ push(eax); // received 2047 AsmPush(eax); // received
2022 2048
2023 // result = receiver[f](arg); 2049 // result = receiver[f](arg);
2024 __ bind(&l_call); 2050 __ bind(&l_call);
2025 __ mov(edx, Operand(esp, kPointerSize)); 2051 __ mov(edx, Operand(esp, kPointerSize));
2026 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2052 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2027 CallIC(ic, TypeFeedbackId::None()); 2053 CallIC(ic, TypeFeedbackId::None());
2028 __ mov(edi, eax); 2054 __ mov(edi, eax);
2029 __ mov(Operand(esp, 2 * kPointerSize), edi); 2055 __ mov(Operand(esp, 2 * kPointerSize), edi);
2030 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); 2056 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2031 __ CallStub(&stub); 2057 AsmCallStub(&stub, 2);
2032 2058
2033 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2059 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2034 __ Drop(1); // The function is still on the stack; drop it. 2060 AsmDrop(1); // The key is still on the stack; drop it.
2035 2061
2036 // if (!result.done) goto l_try; 2062 // if (!result.done) goto l_try;
2037 __ bind(&l_loop); 2063 __ bind(&l_loop);
2038 __ push(eax); // save result 2064 AsmPush(eax); // save result
2039 __ mov(edx, eax); // result 2065 __ mov(edx, eax); // result
2040 __ mov(ecx, isolate()->factory()->done_string()); // "done" 2066 __ mov(ecx, isolate()->factory()->done_string()); // "done"
2041 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax 2067 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
2042 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2068 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2043 CallIC(bool_ic); 2069 CallIC(bool_ic);
2044 __ test(eax, eax); 2070 __ test(eax, eax);
2045 __ j(zero, &l_try); 2071 __ j(zero, &l_try);
2046 2072
2047 // result.value 2073 // result.value
2048 __ pop(edx); // result 2074 AsmPop(edx); // result
2049 __ mov(ecx, isolate()->factory()->value_string()); // "value" 2075 __ mov(ecx, isolate()->factory()->value_string()); // "value"
2050 CallLoadIC(NOT_CONTEXTUAL); // result.value in eax 2076 CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
2051 context()->DropAndPlug(2, eax); // drop iter and g 2077 context()->DropAndPlug(2, eax); // drop iter and g
2052 break; 2078 break;
2053 } 2079 }
2054 } 2080 }
2055 } 2081 }
2056 2082
2057 2083
2058 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2084 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2059 Expression *value, 2085 Expression *value,
2060 JSGeneratorObject::ResumeMode resume_mode) { 2086 JSGeneratorObject::ResumeMode resume_mode) {
2061 // The value stays in eax, and is ultimately read by the resumed generator, as 2087 // The value stays in eax, and is ultimately read by the resumed generator, as
2062 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it 2088 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it
2063 // is read to throw the value when the resumed generator is already closed. 2089 // is read to throw the value when the resumed generator is already closed.
2064 // ebx will hold the generator object until the activation has been resumed. 2090 // ebx will hold the generator object until the activation has been resumed.
2065 VisitForStackValue(generator); 2091 VisitForStackValue(generator);
2066 VisitForAccumulatorValue(value); 2092 VisitForAccumulatorValue(value);
2067 __ pop(ebx); 2093 AsmPop(ebx);
2068 2094
2069 // Check generator state. 2095 // Check generator state.
2070 Label wrong_state, closed_state, done; 2096 Label wrong_state, closed_state, done;
2071 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 2097 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2072 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 2098 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2073 __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset), 2099 __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
2074 Immediate(Smi::FromInt(0))); 2100 Immediate(Smi::FromInt(0)));
2075 __ j(equal, &closed_state); 2101 __ j(equal, &closed_state);
2076 __ j(less, &wrong_state); 2102 __ j(less, &wrong_state);
2077 2103
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2140 __ push(result_register()); 2166 __ push(result_register());
2141 __ Push(Smi::FromInt(resume_mode)); 2167 __ Push(Smi::FromInt(resume_mode));
2142 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); 2168 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3);
2143 // Not reached: the runtime call returns elsewhere. 2169 // Not reached: the runtime call returns elsewhere.
2144 __ Abort(kGeneratorFailedToResume); 2170 __ Abort(kGeneratorFailedToResume);
2145 2171
2146 // Reach here when generator is closed. 2172 // Reach here when generator is closed.
2147 __ bind(&closed_state); 2173 __ bind(&closed_state);
2148 if (resume_mode == JSGeneratorObject::NEXT) { 2174 if (resume_mode == JSGeneratorObject::NEXT) {
2149 // Return completed iterator result when generator is closed. 2175 // Return completed iterator result when generator is closed.
2150 __ push(Immediate(isolate()->factory()->undefined_value())); 2176 AsmPushHandle(isolate()->factory()->undefined_value());
2151 // Pop value from top-of-stack slot; box result into result register. 2177 // Pop value from top-of-stack slot; box result into result register.
2152 EmitCreateIteratorResult(true); 2178 EmitCreateIteratorResult(true);
2153 } else { 2179 } else {
2154 // Throw the provided value. 2180 // Throw the provided value.
2155 __ push(eax); 2181 AsmPush(eax);
2156 __ CallRuntime(Runtime::kHiddenThrow, 1); 2182 AsmCallRuntime(Runtime::kHiddenThrow, 1);
2157 } 2183 }
2158 __ jmp(&done); 2184 __ jmp(&done);
2159 2185
2160 // Throw error if we attempt to operate on a running generator. 2186 // Throw error if we attempt to operate on a running generator.
2161 __ bind(&wrong_state); 2187 __ bind(&wrong_state);
2162 __ push(ebx); 2188 AsmPush(ebx);
2163 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); 2189 AsmCallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
2164 2190
2165 __ bind(&done); 2191 __ bind(&done);
2166 context()->Plug(result_register()); 2192 context()->Plug(result_register());
2167 } 2193 }
2168 2194
2169 2195
2170 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { 2196 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2171 Label gc_required; 2197 Label gc_required;
2172 Label allocated; 2198 Label allocated;
2173 2199
2174 Handle<Map> map(isolate()->native_context()->iterator_result_map()); 2200 Handle<Map> map(isolate()->native_context()->iterator_result_map());
2175 2201
2176 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); 2202 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
2177 __ jmp(&allocated); 2203 __ jmp(&allocated);
2178 2204
2179 __ bind(&gc_required); 2205 __ bind(&gc_required);
2180 __ Push(Smi::FromInt(map->instance_size())); 2206 AsmPushSmi(Smi::FromInt(map->instance_size()));
2181 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); 2207 AsmCallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
2182 __ mov(context_register(), 2208 __ mov(context_register(),
2183 Operand(ebp, StandardFrameConstants::kContextOffset)); 2209 Operand(ebp, StandardFrameConstants::kContextOffset));
2184 2210
2185 __ bind(&allocated); 2211 __ bind(&allocated);
2186 __ mov(ebx, map); 2212 __ mov(ebx, map);
2187 __ pop(ecx); 2213 AsmPop(ecx);
2188 __ mov(edx, isolate()->factory()->ToBoolean(done)); 2214 __ mov(edx, isolate()->factory()->ToBoolean(done));
2189 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2215 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2190 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); 2216 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
2191 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), 2217 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
2192 isolate()->factory()->empty_fixed_array()); 2218 isolate()->factory()->empty_fixed_array());
2193 __ mov(FieldOperand(eax, JSObject::kElementsOffset), 2219 __ mov(FieldOperand(eax, JSObject::kElementsOffset),
2194 isolate()->factory()->empty_fixed_array()); 2220 isolate()->factory()->empty_fixed_array());
2195 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); 2221 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx);
2196 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); 2222 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx);
2197 2223
(...skipping 21 matching lines...) Expand all
2219 2245
2220 2246
2221 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2247 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2222 Token::Value op, 2248 Token::Value op,
2223 OverwriteMode mode, 2249 OverwriteMode mode,
2224 Expression* left, 2250 Expression* left,
2225 Expression* right) { 2251 Expression* right) {
2226 // Do combined smi check of the operands. Left operand is on the 2252 // Do combined smi check of the operands. Left operand is on the
2227 // stack. Right operand is in eax. 2253 // stack. Right operand is in eax.
2228 Label smi_case, done, stub_call; 2254 Label smi_case, done, stub_call;
2229 __ pop(edx); 2255 AsmPop(edx);
2230 __ mov(ecx, eax); 2256 __ mov(ecx, eax);
2231 __ or_(eax, edx); 2257 __ or_(eax, edx);
2232 JumpPatchSite patch_site(masm_); 2258 JumpPatchSite patch_site(masm_);
2233 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 2259 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2234 2260
2235 __ bind(&stub_call); 2261 __ bind(&stub_call);
2236 __ mov(eax, ecx); 2262 __ mov(eax, ecx);
2237 BinaryOpICStub stub(isolate(), op, mode); 2263 BinaryOpICStub stub(isolate(), op, mode);
2238 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); 2264 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2239 patch_site.EmitPatchInfo(); 2265 patch_site.EmitPatchInfo();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2309 } 2335 }
2310 2336
2311 __ bind(&done); 2337 __ bind(&done);
2312 context()->Plug(eax); 2338 context()->Plug(eax);
2313 } 2339 }
2314 2340
2315 2341
2316 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2342 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2317 Token::Value op, 2343 Token::Value op,
2318 OverwriteMode mode) { 2344 OverwriteMode mode) {
2319 __ pop(edx); 2345 AsmPop(edx);
2320 BinaryOpICStub stub(isolate(), op, mode); 2346 BinaryOpICStub stub(isolate(), op, mode);
2321 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2347 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2322 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); 2348 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2323 patch_site.EmitPatchInfo(); 2349 patch_site.EmitPatchInfo();
2324 context()->Plug(eax); 2350 context()->Plug(eax);
2325 } 2351 }
2326 2352
2327 2353
2328 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2354 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2329 ASSERT(expr->IsValidReferenceExpression()); 2355 ASSERT(expr->IsValidReferenceExpression());
(...skipping 10 matching lines...) Expand all
2340 } 2366 }
2341 2367
2342 switch (assign_type) { 2368 switch (assign_type) {
2343 case VARIABLE: { 2369 case VARIABLE: {
2344 Variable* var = expr->AsVariableProxy()->var(); 2370 Variable* var = expr->AsVariableProxy()->var();
2345 EffectContext context(this); 2371 EffectContext context(this);
2346 EmitVariableAssignment(var, Token::ASSIGN); 2372 EmitVariableAssignment(var, Token::ASSIGN);
2347 break; 2373 break;
2348 } 2374 }
2349 case NAMED_PROPERTY: { 2375 case NAMED_PROPERTY: {
2350 __ push(eax); // Preserve value. 2376 AsmPush(eax); // Preserve value.
2351 VisitForAccumulatorValue(prop->obj()); 2377 VisitForAccumulatorValue(prop->obj());
2352 __ mov(edx, eax); 2378 __ mov(edx, eax);
2353 __ pop(eax); // Restore value. 2379 AsmPop(eax); // Restore value.
2354 __ mov(ecx, prop->key()->AsLiteral()->value()); 2380 __ mov(ecx, prop->key()->AsLiteral()->value());
2355 CallStoreIC(); 2381 CallStoreIC();
2356 break; 2382 break;
2357 } 2383 }
2358 case KEYED_PROPERTY: { 2384 case KEYED_PROPERTY: {
2359 __ push(eax); // Preserve value. 2385 AsmPush(eax); // Preserve value.
2360 VisitForStackValue(prop->obj()); 2386 VisitForStackValue(prop->obj());
2361 VisitForAccumulatorValue(prop->key()); 2387 VisitForAccumulatorValue(prop->key());
2362 __ mov(ecx, eax); 2388 __ mov(ecx, eax);
2363 __ pop(edx); // Receiver. 2389 AsmPop(edx); // Receiver.
2364 __ pop(eax); // Restore value. 2390 AsmPop(eax); // Restore value.
2365 Handle<Code> ic = strict_mode() == SLOPPY 2391 Handle<Code> ic = strict_mode() == SLOPPY
2366 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2392 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2367 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2393 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2368 CallIC(ic); 2394 CallIC(ic);
2369 break; 2395 break;
2370 } 2396 }
2371 } 2397 }
2372 context()->Plug(eax); 2398 context()->Plug(eax);
2373 } 2399 }
2374 2400
(...skipping 24 matching lines...) Expand all
2399 if (var->IsUnallocated()) { 2425 if (var->IsUnallocated()) {
2400 // Global var, const, or let. 2426 // Global var, const, or let.
2401 __ mov(ecx, var->name()); 2427 __ mov(ecx, var->name());
2402 __ mov(edx, GlobalObjectOperand()); 2428 __ mov(edx, GlobalObjectOperand());
2403 CallStoreIC(); 2429 CallStoreIC();
2404 2430
2405 } else if (op == Token::INIT_CONST_LEGACY) { 2431 } else if (op == Token::INIT_CONST_LEGACY) {
2406 // Const initializers need a write barrier. 2432 // Const initializers need a write barrier.
2407 ASSERT(!var->IsParameter()); // No const parameters. 2433 ASSERT(!var->IsParameter()); // No const parameters.
2408 if (var->IsLookupSlot()) { 2434 if (var->IsLookupSlot()) {
2409 __ push(eax); 2435 AsmPush(eax);
2410 __ push(esi); 2436 AsmPush(esi);
2411 __ push(Immediate(var->name())); 2437 AsmPushHandle(var->name());
2412 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); 2438 AsmCallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
2413 } else { 2439 } else {
2414 ASSERT(var->IsStackLocal() || var->IsContextSlot()); 2440 ASSERT(var->IsStackLocal() || var->IsContextSlot());
2415 Label skip; 2441 Label skip;
2416 MemOperand location = VarOperand(var, ecx); 2442 MemOperand location = VarOperand(var, ecx);
2417 __ mov(edx, location); 2443 __ mov(edx, location);
2418 __ cmp(edx, isolate()->factory()->the_hole_value()); 2444 __ cmp(edx, isolate()->factory()->the_hole_value());
2419 __ j(not_equal, &skip, Label::kNear); 2445 __ j(not_equal, &skip, Label::kNear);
2420 EmitStoreToStackLocalOrContextSlot(var, location); 2446 EmitStoreToStackLocalOrContextSlot(var, location);
2421 __ bind(&skip); 2447 __ bind(&skip);
2422 } 2448 }
2423 2449
2424 } else if (var->mode() == LET && op != Token::INIT_LET) { 2450 } else if (var->mode() == LET && op != Token::INIT_LET) {
2425 // Non-initializing assignment to let variable needs a write barrier. 2451 // Non-initializing assignment to let variable needs a write barrier.
2426 if (var->IsLookupSlot()) { 2452 if (var->IsLookupSlot()) {
2427 EmitCallStoreContextSlot(var->name(), strict_mode()); 2453 EmitCallStoreContextSlot(var->name(), strict_mode());
2428 } else { 2454 } else {
2429 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2455 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2430 Label assign; 2456 Label assign;
2431 MemOperand location = VarOperand(var, ecx); 2457 MemOperand location = VarOperand(var, ecx);
2432 __ mov(edx, location); 2458 __ mov(edx, location);
2433 __ cmp(edx, isolate()->factory()->the_hole_value()); 2459 __ cmp(edx, isolate()->factory()->the_hole_value());
2434 __ j(not_equal, &assign, Label::kNear); 2460 __ j(not_equal, &assign, Label::kNear);
2435 __ push(Immediate(var->name())); 2461 AsmPushHandle(var->name());
2436 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); 2462 AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
2437 __ bind(&assign); 2463 __ bind(&assign);
2438 EmitStoreToStackLocalOrContextSlot(var, location); 2464 EmitStoreToStackLocalOrContextSlot(var, location);
2439 } 2465 }
2440 2466
2441 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2467 } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2442 // Assignment to var or initializing assignment to let/const 2468 // Assignment to var or initializing assignment to let/const
2443 // in harmony mode. 2469 // in harmony mode.
2444 if (var->IsLookupSlot()) { 2470 if (var->IsLookupSlot()) {
2445 EmitCallStoreContextSlot(var->name(), strict_mode()); 2471 EmitCallStoreContextSlot(var->name(), strict_mode());
2446 } else { 2472 } else {
(...skipping 17 matching lines...) Expand all
2464 // eax : value 2490 // eax : value
2465 // esp[0] : receiver 2491 // esp[0] : receiver
2466 2492
2467 Property* prop = expr->target()->AsProperty(); 2493 Property* prop = expr->target()->AsProperty();
2468 ASSERT(prop != NULL); 2494 ASSERT(prop != NULL);
2469 ASSERT(prop->key()->AsLiteral() != NULL); 2495 ASSERT(prop->key()->AsLiteral() != NULL);
2470 2496
2471 // Record source code position before IC call. 2497 // Record source code position before IC call.
2472 SetSourcePosition(expr->position()); 2498 SetSourcePosition(expr->position());
2473 __ mov(ecx, prop->key()->AsLiteral()->value()); 2499 __ mov(ecx, prop->key()->AsLiteral()->value());
2474 __ pop(edx); 2500 AsmPop(edx);
2475 CallStoreIC(expr->AssignmentFeedbackId()); 2501 CallStoreIC(expr->AssignmentFeedbackId());
2476 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2502 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2477 context()->Plug(eax); 2503 context()->Plug(eax);
2478 } 2504 }
2479 2505
2480 2506
2481 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2507 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2482 // Assignment to a property, using a keyed store IC. 2508 // Assignment to a property, using a keyed store IC.
2483 // eax : value 2509 // eax : value
2484 // esp[0] : key 2510 // esp[0] : key
2485 // esp[kPointerSize] : receiver 2511 // esp[kPointerSize] : receiver
2486 2512
2487 __ pop(ecx); // Key. 2513 AsmPop(ecx); // Key.
2488 __ pop(edx); 2514 AsmPop(edx);
2489 // Record source code position before IC call. 2515 // Record source code position before IC call.
2490 SetSourcePosition(expr->position()); 2516 SetSourcePosition(expr->position());
2491 Handle<Code> ic = strict_mode() == SLOPPY 2517 Handle<Code> ic = strict_mode() == SLOPPY
2492 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2518 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2493 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2519 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2494 CallIC(ic, expr->AssignmentFeedbackId()); 2520 CallIC(ic, expr->AssignmentFeedbackId());
2495 2521
2496 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2522 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2497 context()->Plug(eax); 2523 context()->Plug(eax);
2498 } 2524 }
2499 2525
2500 2526
2501 void FullCodeGenerator::VisitProperty(Property* expr) { 2527 void FullCodeGenerator::VisitProperty(Property* expr) {
2502 Comment cmnt(masm_, "[ Property"); 2528 Comment cmnt(masm_, "[ Property");
2503 Expression* key = expr->key(); 2529 Expression* key = expr->key();
2504 2530
2505 if (key->IsPropertyName()) { 2531 if (key->IsPropertyName()) {
2506 VisitForAccumulatorValue(expr->obj()); 2532 VisitForAccumulatorValue(expr->obj());
2507 __ mov(edx, result_register()); 2533 __ mov(edx, result_register());
2508 EmitNamedPropertyLoad(expr); 2534 EmitNamedPropertyLoad(expr);
2509 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2535 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2510 context()->Plug(eax); 2536 context()->Plug(eax);
2511 } else { 2537 } else {
2512 VisitForStackValue(expr->obj()); 2538 VisitForStackValue(expr->obj());
2513 VisitForAccumulatorValue(expr->key()); 2539 VisitForAccumulatorValue(expr->key());
2514 __ pop(edx); // Object. 2540 AsmPop(edx); // Object.
2515 __ mov(ecx, result_register()); // Key. 2541 __ mov(ecx, result_register()); // Key.
2516 EmitKeyedPropertyLoad(expr); 2542 EmitKeyedPropertyLoad(expr);
2517 context()->Plug(eax); 2543 context()->Plug(eax);
2518 } 2544 }
2519 } 2545 }
2520 2546
2521 2547
2522 void FullCodeGenerator::CallIC(Handle<Code> code, 2548 void FullCodeGenerator::CallIC(Handle<Code> code,
2523 TypeFeedbackId ast_id) { 2549 TypeFeedbackId ast_id) {
2524 ic_total_count_++; 2550 ic_total_count_++;
2525 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2551 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2526 } 2552 }
2527 2553
2528 2554
2529 // Code common for calls using the IC. 2555 // Code common for calls using the IC.
2530 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 2556 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2531 Expression* callee = expr->expression(); 2557 Expression* callee = expr->expression();
2532 2558
2533 CallIC::CallType call_type = callee->IsVariableProxy() 2559 CallIC::CallType call_type = callee->IsVariableProxy()
2534 ? CallIC::FUNCTION 2560 ? CallIC::FUNCTION
2535 : CallIC::METHOD; 2561 : CallIC::METHOD;
2536 // Get the target function. 2562 // Get the target function.
2537 if (call_type == CallIC::FUNCTION) { 2563 if (call_type == CallIC::FUNCTION) {
2538 { StackValueContext context(this); 2564 { StackValueContext context(this);
2539 EmitVariableLoad(callee->AsVariableProxy()); 2565 EmitVariableLoad(callee->AsVariableProxy());
2540 PrepareForBailout(callee, NO_REGISTERS); 2566 PrepareForBailout(callee, NO_REGISTERS);
2541 } 2567 }
2542 // Push undefined as receiver. This is patched in the method prologue if it 2568 // Push undefined as receiver. This is patched in the method prologue if it
2543 // is a sloppy mode method. 2569 // is a sloppy mode method.
2544 __ push(Immediate(isolate()->factory()->undefined_value())); 2570 AsmPushHandle(isolate()->factory()->undefined_value());
2545 } else { 2571 } else {
2546 // Load the function from the receiver. 2572 // Load the function from the receiver.
2547 ASSERT(callee->IsProperty()); 2573 ASSERT(callee->IsProperty());
2548 __ mov(edx, Operand(esp, 0)); 2574 __ mov(edx, Operand(esp, 0));
2549 EmitNamedPropertyLoad(callee->AsProperty()); 2575 EmitNamedPropertyLoad(callee->AsProperty());
2550 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2576 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2551 // Push the target function under the receiver. 2577 // Push the target function under the receiver.
2552 __ push(Operand(esp, 0)); 2578 AsmPush(Operand(esp, 0));
2553 __ mov(Operand(esp, kPointerSize), eax); 2579 __ mov(Operand(esp, kPointerSize), eax);
2554 } 2580 }
2555 2581
2556 EmitCall(expr, call_type); 2582 EmitCall(expr, call_type);
2557 } 2583 }
2558 2584
2559 2585
2560 // Code common for calls using the IC. 2586 // Code common for calls using the IC.
2561 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2587 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2562 Expression* key) { 2588 Expression* key) {
2563 // Load the key. 2589 // Load the key.
2564 VisitForAccumulatorValue(key); 2590 VisitForAccumulatorValue(key);
2565 2591
2566 Expression* callee = expr->expression(); 2592 Expression* callee = expr->expression();
2567 2593
2568 // Load the function from the receiver. 2594 // Load the function from the receiver.
2569 ASSERT(callee->IsProperty()); 2595 ASSERT(callee->IsProperty());
2570 __ mov(edx, Operand(esp, 0)); 2596 __ mov(edx, Operand(esp, 0));
2571 // Move the key into the right register for the keyed load IC. 2597 // Move the key into the right register for the keyed load IC.
2572 __ mov(ecx, eax); 2598 __ mov(ecx, eax);
2573 EmitKeyedPropertyLoad(callee->AsProperty()); 2599 EmitKeyedPropertyLoad(callee->AsProperty());
2574 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2600 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2575 2601
2576 // Push the target function under the receiver. 2602 // Push the target function under the receiver.
2577 __ push(Operand(esp, 0)); 2603 AsmPush(Operand(esp, 0));
2578 __ mov(Operand(esp, kPointerSize), eax); 2604 __ mov(Operand(esp, kPointerSize), eax);
2579 2605
2580 EmitCall(expr, CallIC::METHOD); 2606 EmitCall(expr, CallIC::METHOD);
2581 } 2607 }
2582 2608
2583 2609
2584 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) { 2610 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2585 // Load the arguments. 2611 // Load the arguments.
2586 ZoneList<Expression*>* args = expr->arguments(); 2612 ZoneList<Expression*>* args = expr->arguments();
2587 int arg_count = args->length(); 2613 int arg_count = args->length();
2588 { PreservePositionScope scope(masm()->positions_recorder()); 2614 { PreservePositionScope scope(masm()->positions_recorder());
2589 for (int i = 0; i < arg_count; i++) { 2615 for (int i = 0; i < arg_count; i++) {
2590 VisitForStackValue(args->at(i)); 2616 VisitForStackValue(args->at(i));
2591 } 2617 }
2592 } 2618 }
2593 2619
2594 // Record source position of the IC call. 2620 // Record source position of the IC call.
2595 SetSourcePosition(expr->position()); 2621 SetSourcePosition(expr->position());
2596 Handle<Code> ic = CallIC::initialize_stub( 2622 Handle<Code> ic = CallIC::initialize_stub(
2597 isolate(), arg_count, call_type); 2623 isolate(), arg_count, call_type);
2598 __ Move(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot()))); 2624 __ Move(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
2599 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2625 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2600 // Don't assign a type feedback id to the IC, since type feedback is provided 2626 // Don't assign a type feedback id to the IC, since type feedback is provided
2601 // by the vector above. 2627 // by the vector above.
2602 CallIC(ic); 2628 CallIC(ic);
2629 UpdateStackHeight(-(arg_count + 1));
2603 2630
2604 RecordJSReturnSite(expr); 2631 RecordJSReturnSite(expr);
2605
2606 // Restore context register. 2632 // Restore context register.
2607 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2633 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2608 2634
2609 context()->DropAndPlug(1, eax); 2635 context()->DropAndPlug(1, eax);
2610 } 2636 }
2611 2637
2612 2638
2613 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2639 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2614 // Push copy of the first argument or undefined if it doesn't exist. 2640 // Push copy of the first argument or undefined if it doesn't exist.
2615 if (arg_count > 0) { 2641 if (arg_count > 0) {
2616 __ push(Operand(esp, arg_count * kPointerSize)); 2642 AsmPush(Operand(esp, arg_count * kPointerSize));
2617 } else { 2643 } else {
2618 __ push(Immediate(isolate()->factory()->undefined_value())); 2644 AsmPushHandle(isolate()->factory()->undefined_value());
2619 } 2645 }
2620 2646
2621 // Push the receiver of the enclosing function. 2647 // Push the receiver of the enclosing function.
2622 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); 2648 AsmPush(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2623 // Push the language mode. 2649 // Push the language mode.
2624 __ push(Immediate(Smi::FromInt(strict_mode()))); 2650 AsmPushSmi(Smi::FromInt(strict_mode()));
2625 2651
2626 // Push the start position of the scope the calls resides in. 2652 // Push the start position of the scope the calls resides in.
2627 __ push(Immediate(Smi::FromInt(scope()->start_position()))); 2653 AsmPushSmi(Smi::FromInt(scope()->start_position()));
2628 2654
2629 // Do the runtime call. 2655 // Do the runtime call.
2630 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); 2656 AsmCallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
2631 } 2657 }
2632 2658
2633 2659
2634 void FullCodeGenerator::VisitCall(Call* expr) { 2660 void FullCodeGenerator::VisitCall(Call* expr) {
2635 #ifdef DEBUG 2661 #ifdef DEBUG
2636 // We want to verify that RecordJSReturnSite gets called on all paths 2662 // We want to verify that RecordJSReturnSite gets called on all paths
2637 // through this function. Avoid early returns. 2663 // through this function. Avoid early returns.
2638 expr->return_is_recorded_ = false; 2664 expr->return_is_recorded_ = false;
2639 #endif 2665 #endif
2640 2666
2641 Comment cmnt(masm_, "[ Call"); 2667 Comment cmnt(masm_, "[ Call");
2642 Expression* callee = expr->expression(); 2668 Expression* callee = expr->expression();
2643 Call::CallType call_type = expr->GetCallType(isolate()); 2669 Call::CallType call_type = expr->GetCallType(isolate());
2644 2670
2645 if (call_type == Call::POSSIBLY_EVAL_CALL) { 2671 if (call_type == Call::POSSIBLY_EVAL_CALL) {
2646 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval 2672 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2647 // to resolve the function we need to call and the receiver of the call. 2673 // to resolve the function we need to call and the receiver of the call.
2648 // Then we call the resolved function using the given arguments. 2674 // Then we call the resolved function using the given arguments.
2649 ZoneList<Expression*>* args = expr->arguments(); 2675 ZoneList<Expression*>* args = expr->arguments();
2650 int arg_count = args->length(); 2676 int arg_count = args->length();
2651 { PreservePositionScope pos_scope(masm()->positions_recorder()); 2677 { PreservePositionScope pos_scope(masm()->positions_recorder());
2652 VisitForStackValue(callee); 2678 VisitForStackValue(callee);
2653 // Reserved receiver slot. 2679 // Reserved receiver slot.
2654 __ push(Immediate(isolate()->factory()->undefined_value())); 2680 AsmPushHandle(isolate()->factory()->undefined_value());
2655 // Push the arguments. 2681 // Push the arguments.
2656 for (int i = 0; i < arg_count; i++) { 2682 for (int i = 0; i < arg_count; i++) {
2657 VisitForStackValue(args->at(i)); 2683 VisitForStackValue(args->at(i));
2658 } 2684 }
2659 2685
2660 // Push a copy of the function (found below the arguments) and 2686 // Push a copy of the function (found below the arguments) and
2661 // resolve eval. 2687 // resolve eval.
2662 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 2688 AsmPush(Operand(esp, (arg_count + 1) * kPointerSize));
2663 EmitResolvePossiblyDirectEval(arg_count); 2689 EmitResolvePossiblyDirectEval(arg_count);
2664 2690
2665 // The runtime call returns a pair of values in eax (function) and 2691 // The runtime call returns a pair of values in eax (function) and
2666 // edx (receiver). Touch up the stack with the right values. 2692 // edx (receiver). Touch up the stack with the right values.
2667 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2693 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2668 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2694 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2669 } 2695 }
2670 // Record source position for debugger. 2696 // Record source position for debugger.
2671 SetSourcePosition(expr->position()); 2697 SetSourcePosition(expr->position());
2672 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 2698 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
2673 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2699 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2674 __ CallStub(&stub); 2700 __ CallStub(&stub);
2701 UpdateStackHeight(-(arg_count + 1));
2675 RecordJSReturnSite(expr); 2702 RecordJSReturnSite(expr);
2676 // Restore context register. 2703 // Restore context register.
2677 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2704 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2678 context()->DropAndPlug(1, eax); 2705 context()->DropAndPlug(1, eax);
2679 2706
2680 } else if (call_type == Call::GLOBAL_CALL) { 2707 } else if (call_type == Call::GLOBAL_CALL) {
2681 EmitCallWithLoadIC(expr); 2708 EmitCallWithLoadIC(expr);
2682 2709
2683 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2710 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2684 // Call to a lookup slot (dynamically introduced variable). 2711 // Call to a lookup slot (dynamically introduced variable).
2685 VariableProxy* proxy = callee->AsVariableProxy(); 2712 VariableProxy* proxy = callee->AsVariableProxy();
2686 Label slow, done; 2713 Label slow, done;
2687 { PreservePositionScope scope(masm()->positions_recorder()); 2714 { PreservePositionScope scope(masm()->positions_recorder());
2688 // Generate code for loading from variables potentially shadowed by 2715 // Generate code for loading from variables potentially shadowed by
2689 // eval-introduced variables. 2716 // eval-introduced variables.
2690 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2717 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2691 } 2718 }
2692 __ bind(&slow); 2719 __ bind(&slow);
2720 StackHeightWrapper branch_stack_height = CurrentStackHeight();
2693 // Call the runtime to find the function to call (returned in eax) and 2721 // Call the runtime to find the function to call (returned in eax) and
2694 // the object holding it (returned in edx). 2722 // the object holding it (returned in edx).
2695 __ push(context_register()); 2723 AsmPush(context_register());
2696 __ push(Immediate(proxy->name())); 2724 AsmPushHandle(proxy->name());
2697 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); 2725 AsmCallRuntime(Runtime::kHiddenLoadContextSlot, 2);
2698 __ push(eax); // Function. 2726 AsmPush(eax); // Function.
2699 __ push(edx); // Receiver. 2727 AsmPush(edx); // Receiver.
2700 2728
2701 // If fast case code has been generated, emit code to push the function 2729 // If fast case code has been generated, emit code to push the function
2702 // and receiver and have the slow path jump around this code. 2730 // and receiver and have the slow path jump around this code.
2703 if (done.is_linked()) { 2731 if (done.is_linked()) {
2704 Label call; 2732 Label call;
2705 __ jmp(&call, Label::kNear); 2733 __ jmp(&call, Label::kNear);
2706 __ bind(&done); 2734 __ bind(&done);
2735 SetStackHeight(branch_stack_height);
2707 // Push function. 2736 // Push function.
2708 __ push(eax); 2737 AsmPush(eax);
2709 // The receiver is implicitly the global receiver. Indicate this by 2738 // The receiver is implicitly the global receiver. Indicate this by
2710 // passing the hole to the call function stub. 2739 // passing the hole to the call function stub.
2711 __ push(Immediate(isolate()->factory()->undefined_value())); 2740 AsmPushHandle(isolate()->factory()->undefined_value());
2712 __ bind(&call); 2741 __ bind(&call);
2713 } 2742 }
2714 2743
2715 // The receiver is either the global receiver or an object found by 2744 // The receiver is either the global receiver or an object found by
2716 // LoadContextSlot. 2745 // LoadContextSlot.
2717 EmitCall(expr); 2746 EmitCall(expr);
2718 2747
2719 } else if (call_type == Call::PROPERTY_CALL) { 2748 } else if (call_type == Call::PROPERTY_CALL) {
2720 Property* property = callee->AsProperty(); 2749 Property* property = callee->AsProperty();
2721 { PreservePositionScope scope(masm()->positions_recorder()); 2750 { PreservePositionScope scope(masm()->positions_recorder());
2722 VisitForStackValue(property->obj()); 2751 VisitForStackValue(property->obj());
2723 } 2752 }
2724 if (property->key()->IsPropertyName()) { 2753 if (property->key()->IsPropertyName()) {
2725 EmitCallWithLoadIC(expr); 2754 EmitCallWithLoadIC(expr);
2726 } else { 2755 } else {
2727 EmitKeyedCallWithLoadIC(expr, property->key()); 2756 EmitKeyedCallWithLoadIC(expr, property->key());
2728 } 2757 }
2729 2758
2730 } else { 2759 } else {
2731 ASSERT(call_type == Call::OTHER_CALL); 2760 ASSERT(call_type == Call::OTHER_CALL);
2732 // Call to an arbitrary expression not handled specially above. 2761 // Call to an arbitrary expression not handled specially above.
2733 { PreservePositionScope scope(masm()->positions_recorder()); 2762 { PreservePositionScope scope(masm()->positions_recorder());
2734 VisitForStackValue(callee); 2763 VisitForStackValue(callee);
2735 } 2764 }
2736 __ push(Immediate(isolate()->factory()->undefined_value())); 2765 AsmPushHandle(isolate()->factory()->undefined_value());
2737 // Emit function call. 2766 // Emit function call.
2738 EmitCall(expr); 2767 EmitCall(expr);
2739 } 2768 }
2740 2769
2741 #ifdef DEBUG 2770 #ifdef DEBUG
2742 // RecordJSReturnSite should have been called. 2771 // RecordJSReturnSite should have been called.
2743 ASSERT(expr->return_is_recorded_); 2772 ASSERT(expr->return_is_recorded_);
2744 #endif 2773 #endif
2745 } 2774 }
2746 2775
(...skipping 29 matching lines...) Expand all
2776 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2805 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2777 ASSERT(expr->AllocationSiteFeedbackSlot() == 2806 ASSERT(expr->AllocationSiteFeedbackSlot() ==
2778 expr->CallNewFeedbackSlot() + 1); 2807 expr->CallNewFeedbackSlot() + 1);
2779 } 2808 }
2780 2809
2781 __ LoadHeapObject(ebx, FeedbackVector()); 2810 __ LoadHeapObject(ebx, FeedbackVector());
2782 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2811 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
2783 2812
2784 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); 2813 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
2785 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 2814 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2815 UpdateStackHeight(-(arg_count + 1));
2786 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2816 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2787 context()->Plug(eax); 2817 context()->Plug(eax);
2788 } 2818 }
2789 2819
2790 2820
2791 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2821 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2792 ZoneList<Expression*>* args = expr->arguments(); 2822 ZoneList<Expression*>* args = expr->arguments();
2793 ASSERT(args->length() == 1); 2823 ASSERT(args->length() == 1);
2794 2824
2795 VisitForAccumulatorValue(args->at(0)); 2825 VisitForAccumulatorValue(args->at(0));
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3133 VisitForStackValue(args->at(0)); 3163 VisitForStackValue(args->at(0));
3134 VisitForAccumulatorValue(args->at(1)); 3164 VisitForAccumulatorValue(args->at(1));
3135 3165
3136 Label materialize_true, materialize_false; 3166 Label materialize_true, materialize_false;
3137 Label* if_true = NULL; 3167 Label* if_true = NULL;
3138 Label* if_false = NULL; 3168 Label* if_false = NULL;
3139 Label* fall_through = NULL; 3169 Label* fall_through = NULL;
3140 context()->PrepareTest(&materialize_true, &materialize_false, 3170 context()->PrepareTest(&materialize_true, &materialize_false,
3141 &if_true, &if_false, &fall_through); 3171 &if_true, &if_false, &fall_through);
3142 3172
3143 __ pop(ebx); 3173 AsmPop(ebx);
3144 __ cmp(eax, ebx); 3174 __ cmp(eax, ebx);
3145 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3175 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3146 Split(equal, if_true, if_false, fall_through); 3176 Split(equal, if_true, if_false, fall_through);
3147 3177
3148 context()->Plug(if_true, if_false); 3178 context()->Plug(if_true, if_false);
3149 } 3179 }
3150 3180
3151 3181
3152 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { 3182 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3153 ZoneList<Expression*>* args = expr->arguments(); 3183 ZoneList<Expression*>* args = expr->arguments();
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
3249 3279
3250 3280
3251 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3281 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3252 // Load the arguments on the stack and call the stub. 3282 // Load the arguments on the stack and call the stub.
3253 SubStringStub stub(isolate()); 3283 SubStringStub stub(isolate());
3254 ZoneList<Expression*>* args = expr->arguments(); 3284 ZoneList<Expression*>* args = expr->arguments();
3255 ASSERT(args->length() == 3); 3285 ASSERT(args->length() == 3);
3256 VisitForStackValue(args->at(0)); 3286 VisitForStackValue(args->at(0));
3257 VisitForStackValue(args->at(1)); 3287 VisitForStackValue(args->at(1));
3258 VisitForStackValue(args->at(2)); 3288 VisitForStackValue(args->at(2));
3259 __ CallStub(&stub); 3289 AsmCallStub(&stub, 3);
3260 context()->Plug(eax); 3290 context()->Plug(eax);
3261 } 3291 }
3262 3292
3263 3293
3264 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 3294 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3265 // Load the arguments on the stack and call the stub. 3295 // Load the arguments on the stack and call the stub.
3266 RegExpExecStub stub(isolate()); 3296 RegExpExecStub stub(isolate());
3267 ZoneList<Expression*>* args = expr->arguments(); 3297 ZoneList<Expression*>* args = expr->arguments();
3268 ASSERT(args->length() == 4); 3298 ASSERT(args->length() == 4);
3269 VisitForStackValue(args->at(0)); 3299 VisitForStackValue(args->at(0));
3270 VisitForStackValue(args->at(1)); 3300 VisitForStackValue(args->at(1));
3271 VisitForStackValue(args->at(2)); 3301 VisitForStackValue(args->at(2));
3272 VisitForStackValue(args->at(3)); 3302 VisitForStackValue(args->at(3));
3273 __ CallStub(&stub); 3303 AsmCallStub(&stub, 4);
3274 context()->Plug(eax); 3304 context()->Plug(eax);
3275 } 3305 }
3276 3306
3277 3307
3278 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 3308 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3279 ZoneList<Expression*>* args = expr->arguments(); 3309 ZoneList<Expression*>* args = expr->arguments();
3280 ASSERT(args->length() == 1); 3310 ASSERT(args->length() == 1);
3281 3311
3282 VisitForAccumulatorValue(args->at(0)); // Load the object. 3312 VisitForAccumulatorValue(args->at(0)); // Load the object.
3283 3313
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 } 3356 }
3327 __ bind(&runtime); 3357 __ bind(&runtime);
3328 __ PrepareCallCFunction(2, scratch); 3358 __ PrepareCallCFunction(2, scratch);
3329 __ mov(Operand(esp, 0), object); 3359 __ mov(Operand(esp, 0), object);
3330 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); 3360 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
3331 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3361 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3332 __ jmp(&done); 3362 __ jmp(&done);
3333 } 3363 }
3334 3364
3335 __ bind(&not_date_object); 3365 __ bind(&not_date_object);
3336 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); 3366 AsmCallRuntime(Runtime::kHiddenThrowNotDateError, 0);
3337 __ bind(&done); 3367 __ bind(&done);
3338 context()->Plug(result); 3368 context()->Plug(result);
3339 } 3369 }
3340 3370
3341 3371
3342 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3372 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3343 ZoneList<Expression*>* args = expr->arguments(); 3373 ZoneList<Expression*>* args = expr->arguments();
3344 ASSERT_EQ(3, args->length()); 3374 ASSERT_EQ(3, args->length());
3345 3375
3346 Register string = eax; 3376 Register string = eax;
3347 Register index = ebx; 3377 Register index = ebx;
3348 Register value = ecx; 3378 Register value = ecx;
3349 3379
3350 VisitForStackValue(args->at(1)); // index 3380 VisitForStackValue(args->at(1)); // index
3351 VisitForStackValue(args->at(2)); // value 3381 VisitForStackValue(args->at(2)); // value
3352 VisitForAccumulatorValue(args->at(0)); // string 3382 VisitForAccumulatorValue(args->at(0)); // string
3353 3383
3354 __ pop(value); 3384 AsmPop(value);
3355 __ pop(index); 3385 AsmPop(index);
3356 3386
3357 if (FLAG_debug_code) { 3387 if (FLAG_debug_code) {
3358 __ test(value, Immediate(kSmiTagMask)); 3388 __ test(value, Immediate(kSmiTagMask));
3359 __ Check(zero, kNonSmiValue); 3389 __ Check(zero, kNonSmiValue);
3360 __ test(index, Immediate(kSmiTagMask)); 3390 __ test(index, Immediate(kSmiTagMask));
3361 __ Check(zero, kNonSmiValue); 3391 __ Check(zero, kNonSmiValue);
3362 } 3392 }
3363 3393
3364 __ SmiUntag(value); 3394 __ SmiUntag(value);
3365 __ SmiUntag(index); 3395 __ SmiUntag(index);
(...skipping 13 matching lines...) Expand all
3379 ZoneList<Expression*>* args = expr->arguments(); 3409 ZoneList<Expression*>* args = expr->arguments();
3380 ASSERT_EQ(3, args->length()); 3410 ASSERT_EQ(3, args->length());
3381 3411
3382 Register string = eax; 3412 Register string = eax;
3383 Register index = ebx; 3413 Register index = ebx;
3384 Register value = ecx; 3414 Register value = ecx;
3385 3415
3386 VisitForStackValue(args->at(1)); // index 3416 VisitForStackValue(args->at(1)); // index
3387 VisitForStackValue(args->at(2)); // value 3417 VisitForStackValue(args->at(2)); // value
3388 VisitForAccumulatorValue(args->at(0)); // string 3418 VisitForAccumulatorValue(args->at(0)); // string
3389 __ pop(value); 3419 AsmPop(value);
3390 __ pop(index); 3420 AsmPop(index);
3391 3421
3392 if (FLAG_debug_code) { 3422 if (FLAG_debug_code) {
3393 __ test(value, Immediate(kSmiTagMask)); 3423 __ test(value, Immediate(kSmiTagMask));
3394 __ Check(zero, kNonSmiValue); 3424 __ Check(zero, kNonSmiValue);
3395 __ test(index, Immediate(kSmiTagMask)); 3425 __ test(index, Immediate(kSmiTagMask));
3396 __ Check(zero, kNonSmiValue); 3426 __ Check(zero, kNonSmiValue);
3397 __ SmiUntag(index); 3427 __ SmiUntag(index);
3398 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3428 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3399 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3429 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3400 __ SmiTag(index); 3430 __ SmiTag(index);
3401 } 3431 }
3402 3432
3403 __ SmiUntag(value); 3433 __ SmiUntag(value);
3404 // No need to untag a smi for two-byte addressing. 3434 // No need to untag a smi for two-byte addressing.
3405 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), 3435 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
3406 value); 3436 value);
3407 context()->Plug(string); 3437 context()->Plug(string);
3408 } 3438 }
3409 3439
3410 3440
3411 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3441 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3412 // Load the arguments on the stack and call the runtime function. 3442 // Load the arguments on the stack and call the runtime function.
3413 ZoneList<Expression*>* args = expr->arguments(); 3443 ZoneList<Expression*>* args = expr->arguments();
3414 ASSERT(args->length() == 2); 3444 ASSERT(args->length() == 2);
3415 VisitForStackValue(args->at(0)); 3445 VisitForStackValue(args->at(0));
3416 VisitForStackValue(args->at(1)); 3446 VisitForStackValue(args->at(1));
3417 3447
3418 MathPowStub stub(isolate(), MathPowStub::ON_STACK); 3448 MathPowStub stub(isolate(), MathPowStub::ON_STACK);
3419 __ CallStub(&stub); 3449 AsmCallStub(&stub, 2);
3420 context()->Plug(eax); 3450 context()->Plug(eax);
3421 } 3451 }
3422 3452
3423 3453
3424 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 3454 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3425 ZoneList<Expression*>* args = expr->arguments(); 3455 ZoneList<Expression*>* args = expr->arguments();
3426 ASSERT(args->length() == 2); 3456 ASSERT(args->length() == 2);
3427 3457
3428 VisitForStackValue(args->at(0)); // Load the object. 3458 VisitForStackValue(args->at(0)); // Load the object.
3429 VisitForAccumulatorValue(args->at(1)); // Load the value. 3459 VisitForAccumulatorValue(args->at(1)); // Load the value.
3430 __ pop(ebx); // eax = value. ebx = object. 3460 AsmPop(ebx); // eax = value. ebx = object.
3431 3461
3432 Label done; 3462 Label done;
3433 // If the object is a smi, return the value. 3463 // If the object is a smi, return the value.
3434 __ JumpIfSmi(ebx, &done, Label::kNear); 3464 __ JumpIfSmi(ebx, &done, Label::kNear);
3435 3465
3436 // If the object is not a value type, return the value. 3466 // If the object is not a value type, return the value.
3437 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 3467 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
3438 __ j(not_equal, &done, Label::kNear); 3468 __ j(not_equal, &done, Label::kNear);
3439 3469
3440 // Store the value. 3470 // Store the value.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3486 ZoneList<Expression*>* args = expr->arguments(); 3516 ZoneList<Expression*>* args = expr->arguments();
3487 ASSERT(args->length() == 2); 3517 ASSERT(args->length() == 2);
3488 3518
3489 VisitForStackValue(args->at(0)); 3519 VisitForStackValue(args->at(0));
3490 VisitForAccumulatorValue(args->at(1)); 3520 VisitForAccumulatorValue(args->at(1));
3491 3521
3492 Register object = ebx; 3522 Register object = ebx;
3493 Register index = eax; 3523 Register index = eax;
3494 Register result = edx; 3524 Register result = edx;
3495 3525
3496 __ pop(object); 3526 AsmPop(object);
3497 3527
3498 Label need_conversion; 3528 Label need_conversion;
3499 Label index_out_of_range; 3529 Label index_out_of_range;
3500 Label done; 3530 Label done;
3501 StringCharCodeAtGenerator generator(object, 3531 StringCharCodeAtGenerator generator(object,
3502 index, 3532 index,
3503 result, 3533 result,
3504 &need_conversion, 3534 &need_conversion,
3505 &need_conversion, 3535 &need_conversion,
3506 &index_out_of_range, 3536 &index_out_of_range,
(...skipping 26 matching lines...) Expand all
3533 ASSERT(args->length() == 2); 3563 ASSERT(args->length() == 2);
3534 3564
3535 VisitForStackValue(args->at(0)); 3565 VisitForStackValue(args->at(0));
3536 VisitForAccumulatorValue(args->at(1)); 3566 VisitForAccumulatorValue(args->at(1));
3537 3567
3538 Register object = ebx; 3568 Register object = ebx;
3539 Register index = eax; 3569 Register index = eax;
3540 Register scratch = edx; 3570 Register scratch = edx;
3541 Register result = eax; 3571 Register result = eax;
3542 3572
3543 __ pop(object); 3573 AsmPop(object);
3544 3574
3545 Label need_conversion; 3575 Label need_conversion;
3546 Label index_out_of_range; 3576 Label index_out_of_range;
3547 Label done; 3577 Label done;
3548 StringCharAtGenerator generator(object, 3578 StringCharAtGenerator generator(object,
3549 index, 3579 index,
3550 scratch, 3580 scratch,
3551 result, 3581 result,
3552 &need_conversion, 3582 &need_conversion,
3553 &need_conversion, 3583 &need_conversion,
(...skipping 21 matching lines...) Expand all
3575 context()->Plug(result); 3605 context()->Plug(result);
3576 } 3606 }
3577 3607
3578 3608
3579 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3609 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3580 ZoneList<Expression*>* args = expr->arguments(); 3610 ZoneList<Expression*>* args = expr->arguments();
3581 ASSERT_EQ(2, args->length()); 3611 ASSERT_EQ(2, args->length());
3582 VisitForStackValue(args->at(0)); 3612 VisitForStackValue(args->at(0));
3583 VisitForAccumulatorValue(args->at(1)); 3613 VisitForAccumulatorValue(args->at(1));
3584 3614
3585 __ pop(edx); 3615 AsmPop(edx);
3586 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); 3616 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3587 __ CallStub(&stub); 3617 __ CallStub(&stub);
3588 context()->Plug(eax); 3618 context()->Plug(eax);
3589 } 3619 }
3590 3620
3591 3621
3592 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3622 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3593 ZoneList<Expression*>* args = expr->arguments(); 3623 ZoneList<Expression*>* args = expr->arguments();
3594 ASSERT_EQ(2, args->length()); 3624 ASSERT_EQ(2, args->length());
3595 3625
3596 VisitForStackValue(args->at(0)); 3626 VisitForStackValue(args->at(0));
3597 VisitForStackValue(args->at(1)); 3627 VisitForStackValue(args->at(1));
3598 3628
3599 StringCompareStub stub(isolate()); 3629 StringCompareStub stub(isolate());
3600 __ CallStub(&stub); 3630 AsmCallStub(&stub, 2);
3601 context()->Plug(eax); 3631 context()->Plug(eax);
3602 } 3632 }
3603 3633
3604 3634
3605 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 3635 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3606 ZoneList<Expression*>* args = expr->arguments(); 3636 ZoneList<Expression*>* args = expr->arguments();
3607 ASSERT(args->length() >= 2); 3637 ASSERT(args->length() >= 2);
3608 3638
3609 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3639 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3610 for (int i = 0; i < arg_count + 1; ++i) { 3640 for (int i = 0; i < arg_count + 1; ++i) {
3611 VisitForStackValue(args->at(i)); 3641 VisitForStackValue(args->at(i));
3612 } 3642 }
3613 VisitForAccumulatorValue(args->last()); // Function. 3643 VisitForAccumulatorValue(args->last()); // Function.
3614 3644
3615 Label runtime, done; 3645 Label runtime, done;
3616 // Check for non-function argument (including proxy). 3646 // Check for non-function argument (including proxy).
3617 __ JumpIfSmi(eax, &runtime); 3647 __ JumpIfSmi(eax, &runtime);
3618 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 3648 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3649 StackHeightWrapper branch_stack_height = CurrentStackHeight();
3619 __ j(not_equal, &runtime); 3650 __ j(not_equal, &runtime);
3620 3651
3621 // InvokeFunction requires the function in edi. Move it in there. 3652 // InvokeFunction requires the function in edi. Move it in there.
3622 __ mov(edi, result_register()); 3653 __ mov(edi, result_register());
3623 ParameterCount count(arg_count); 3654 ParameterCount count(arg_count);
3624 __ InvokeFunction(edi, count, CALL_FUNCTION, NullCallWrapper()); 3655 __ InvokeFunction(edi, count, CALL_FUNCTION, NullCallWrapper());
3656 UpdateStackHeight(-(arg_count + 1));
3625 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3657 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3626 __ jmp(&done); 3658 __ jmp(&done);
3627 3659
3628 __ bind(&runtime); 3660 __ bind(&runtime);
3629 __ push(eax); 3661 SetStackHeight(branch_stack_height);
3630 __ CallRuntime(Runtime::kCall, args->length()); 3662 AsmPush(eax);
3663 AsmCallRuntime(Runtime::kCall, args->length());
3631 __ bind(&done); 3664 __ bind(&done);
3632 3665
3633 context()->Plug(eax); 3666 context()->Plug(eax);
3634 } 3667 }
3635 3668
3636 3669
3637 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3670 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3638 // Load the arguments on the stack and call the stub. 3671 // Load the arguments on the stack and call the stub.
3639 RegExpConstructResultStub stub(isolate()); 3672 RegExpConstructResultStub stub(isolate());
3640 ZoneList<Expression*>* args = expr->arguments(); 3673 ZoneList<Expression*>* args = expr->arguments();
3641 ASSERT(args->length() == 3); 3674 ASSERT(args->length() == 3);
3642 VisitForStackValue(args->at(0)); 3675 VisitForStackValue(args->at(0));
3643 VisitForStackValue(args->at(1)); 3676 VisitForStackValue(args->at(1));
3644 VisitForAccumulatorValue(args->at(2)); 3677 VisitForAccumulatorValue(args->at(2));
3645 __ pop(ebx); 3678 AsmPop(ebx);
3646 __ pop(ecx); 3679 AsmPop(ecx);
3647 __ CallStub(&stub); 3680 __ CallStub(&stub);
3648 context()->Plug(eax); 3681 context()->Plug(eax);
3649 } 3682 }
3650 3683
3651 3684
3652 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3685 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3653 ZoneList<Expression*>* args = expr->arguments(); 3686 ZoneList<Expression*>* args = expr->arguments();
3654 ASSERT_EQ(2, args->length()); 3687 ASSERT_EQ(2, args->length());
3655 3688
3656 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3689 ASSERT_NE(NULL, args->at(0)->AsLiteral());
(...skipping 25 matching lines...) Expand all
3682 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3715 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3683 // tmp now holds finger offset as a smi. 3716 // tmp now holds finger offset as a smi.
3684 __ cmp(key, FixedArrayElementOperand(cache, tmp)); 3717 __ cmp(key, FixedArrayElementOperand(cache, tmp));
3685 __ j(not_equal, &not_found); 3718 __ j(not_equal, &not_found);
3686 3719
3687 __ mov(eax, FixedArrayElementOperand(cache, tmp, 1)); 3720 __ mov(eax, FixedArrayElementOperand(cache, tmp, 1));
3688 __ jmp(&done); 3721 __ jmp(&done);
3689 3722
3690 __ bind(&not_found); 3723 __ bind(&not_found);
3691 // Call runtime to perform the lookup. 3724 // Call runtime to perform the lookup.
3692 __ push(cache); 3725 AsmPush(cache);
3693 __ push(key); 3726 AsmPush(key);
3694 __ CallRuntime(Runtime::kHiddenGetFromCache, 2); 3727 AsmCallRuntime(Runtime::kHiddenGetFromCache, 2);
3695 3728
3696 __ bind(&done); 3729 __ bind(&done);
3697 context()->Plug(eax); 3730 context()->Plug(eax);
3698 } 3731 }
3699 3732
3700 3733
3701 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3734 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3702 ZoneList<Expression*>* args = expr->arguments(); 3735 ZoneList<Expression*>* args = expr->arguments();
3703 ASSERT(args->length() == 1); 3736 ASSERT(args->length() == 1);
3704 3737
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3760 Register scratch = ebx; 3793 Register scratch = ebx;
3761 3794
3762 Register array_length = edi; 3795 Register array_length = edi;
3763 Register result_pos = no_reg; // Will be edi. 3796 Register result_pos = no_reg; // Will be edi.
3764 3797
3765 // Separator operand is already pushed. 3798 // Separator operand is already pushed.
3766 Operand separator_operand = Operand(esp, 2 * kPointerSize); 3799 Operand separator_operand = Operand(esp, 2 * kPointerSize);
3767 Operand result_operand = Operand(esp, 1 * kPointerSize); 3800 Operand result_operand = Operand(esp, 1 * kPointerSize);
3768 Operand array_length_operand = Operand(esp, 0); 3801 Operand array_length_operand = Operand(esp, 0);
3769 __ sub(esp, Immediate(2 * kPointerSize)); 3802 __ sub(esp, Immediate(2 * kPointerSize));
3803 UpdateStackHeight(2);
3770 __ cld(); 3804 __ cld();
3771 // Check that the array is a JSArray 3805 // Check that the array is a JSArray
3772 __ JumpIfSmi(array, &bailout); 3806 __ JumpIfSmi(array, &bailout);
3773 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3807 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3774 __ j(not_equal, &bailout); 3808 __ j(not_equal, &bailout);
3775 3809
3776 // Check that the array has fast elements. 3810 // Check that the array has fast elements.
3777 __ CheckFastElements(scratch, &bailout); 3811 __ CheckFastElements(scratch, &bailout);
3778 3812
3779 // If the array has length zero, return the empty string. 3813 // If the array has length zero, return the empty string.
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
3986 __ cmp(index, array_length_operand); 4020 __ cmp(index, array_length_operand);
3987 __ j(less, &loop_3); // End while (index < length). 4021 __ j(less, &loop_3); // End while (index < length).
3988 __ jmp(&done); 4022 __ jmp(&done);
3989 4023
3990 4024
3991 __ bind(&bailout); 4025 __ bind(&bailout);
3992 __ mov(result_operand, isolate()->factory()->undefined_value()); 4026 __ mov(result_operand, isolate()->factory()->undefined_value());
3993 __ bind(&done); 4027 __ bind(&done);
3994 __ mov(eax, result_operand); 4028 __ mov(eax, result_operand);
3995 // Drop temp values from the stack, and restore context register. 4029 // Drop temp values from the stack, and restore context register.
3996 __ add(esp, Immediate(3 * kPointerSize)); 4030 AsmDrop(3);
3997 4031
3998 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4032 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3999 context()->Plug(eax); 4033 context()->Plug(eax);
4000 } 4034 }
4001 4035
4002 4036
4003 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4037 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4004 if (expr->function() != NULL && 4038 if (expr->function() != NULL &&
4005 expr->function()->intrinsic_type == Runtime::INLINE) { 4039 expr->function()->intrinsic_type == Runtime::INLINE) {
4006 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4040 Comment cmnt(masm_, "[ InlineRuntimeCall");
4007 EmitInlineRuntimeCall(expr); 4041 EmitInlineRuntimeCall(expr);
4008 return; 4042 return;
4009 } 4043 }
4010 4044
4011 Comment cmnt(masm_, "[ CallRuntime"); 4045 Comment cmnt(masm_, "[ CallRuntime");
4012 ZoneList<Expression*>* args = expr->arguments(); 4046 ZoneList<Expression*>* args = expr->arguments();
4013 4047
4014 if (expr->is_jsruntime()) { 4048 if (expr->is_jsruntime()) {
4015 // Push the builtins object as receiver. 4049 // Push the builtins object as receiver.
4016 __ mov(eax, GlobalObjectOperand()); 4050 __ mov(eax, GlobalObjectOperand());
4017 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); 4051 AsmPush(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
4018 4052
4019 // Load the function from the receiver. 4053 // Load the function from the receiver.
4020 __ mov(edx, Operand(esp, 0)); 4054 __ mov(edx, Operand(esp, 0));
4021 __ mov(ecx, Immediate(expr->name())); 4055 __ mov(ecx, Immediate(expr->name()));
4022 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4056 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4023 4057
4024 // Push the target function under the receiver. 4058 // Push the target function under the receiver.
4025 __ push(Operand(esp, 0)); 4059 AsmPush(Operand(esp, 0));
4026 __ mov(Operand(esp, kPointerSize), eax); 4060 __ mov(Operand(esp, kPointerSize), eax);
4027 4061
4028 // Code common for calls using the IC. 4062 // Code common for calls using the IC.
4029 ZoneList<Expression*>* args = expr->arguments(); 4063 ZoneList<Expression*>* args = expr->arguments();
4030 int arg_count = args->length(); 4064 int arg_count = args->length();
4031 for (int i = 0; i < arg_count; i++) { 4065 for (int i = 0; i < arg_count; i++) {
4032 VisitForStackValue(args->at(i)); 4066 VisitForStackValue(args->at(i));
4033 } 4067 }
4034 4068
4035 // Record source position of the IC call. 4069 // Record source position of the IC call.
4036 SetSourcePosition(expr->position()); 4070 SetSourcePosition(expr->position());
4037 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 4071 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4038 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 4072 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
4039 __ CallStub(&stub); 4073 AsmCallStub(&stub, arg_count + 1);
4040 // Restore context register. 4074 // Restore context register.
4041 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4075 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4042 context()->DropAndPlug(1, eax); 4076 context()->DropAndPlug(1, eax);
4043 4077
4044 } else { 4078 } else {
4045 // Push the arguments ("left-to-right"). 4079 // Push the arguments ("left-to-right").
4046 int arg_count = args->length(); 4080 int arg_count = args->length();
4047 for (int i = 0; i < arg_count; i++) { 4081 for (int i = 0; i < arg_count; i++) {
4048 VisitForStackValue(args->at(i)); 4082 VisitForStackValue(args->at(i));
4049 } 4083 }
4050 4084
4051 // Call the C runtime function. 4085 // Call the C runtime function.
4052 __ CallRuntime(expr->function(), arg_count); 4086 AsmCallRuntime(expr->function(), arg_count);
4053 4087
4054 context()->Plug(eax); 4088 context()->Plug(eax);
4055 } 4089 }
4056 } 4090 }
4057 4091
4058 4092
4059 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4093 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4060 switch (expr->op()) { 4094 switch (expr->op()) {
4061 case Token::DELETE: { 4095 case Token::DELETE: {
4062 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4096 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4063 Property* property = expr->expression()->AsProperty(); 4097 Property* property = expr->expression()->AsProperty();
4064 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4098 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4065 4099
4066 if (property != NULL) { 4100 if (property != NULL) {
4067 VisitForStackValue(property->obj()); 4101 VisitForStackValue(property->obj());
4068 VisitForStackValue(property->key()); 4102 VisitForStackValue(property->key());
4069 __ push(Immediate(Smi::FromInt(strict_mode()))); 4103 AsmPushSmi(Smi::FromInt(strict_mode()));
4070 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4104 AsmInvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
4071 context()->Plug(eax); 4105 context()->Plug(eax);
4072 } else if (proxy != NULL) { 4106 } else if (proxy != NULL) {
4073 Variable* var = proxy->var(); 4107 Variable* var = proxy->var();
4074 // Delete of an unqualified identifier is disallowed in strict mode 4108 // Delete of an unqualified identifier is disallowed in strict mode
4075 // but "delete this" is allowed. 4109 // but "delete this" is allowed.
4076 ASSERT(strict_mode() == SLOPPY || var->is_this()); 4110 ASSERT(strict_mode() == SLOPPY || var->is_this());
4077 if (var->IsUnallocated()) { 4111 if (var->IsUnallocated()) {
4078 __ push(GlobalObjectOperand()); 4112 AsmPush(GlobalObjectOperand());
4079 __ push(Immediate(var->name())); 4113 AsmPushHandle(var->name());
4080 __ push(Immediate(Smi::FromInt(SLOPPY))); 4114 AsmPushSmi(Smi::FromInt(SLOPPY));
4081 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4115 AsmInvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
4082 context()->Plug(eax); 4116 context()->Plug(eax);
4083 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4117 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4084 // Result of deleting non-global variables is false. 'this' is 4118 // Result of deleting non-global variables is false. 'this' is
4085 // not really a variable, though we implement it as one. The 4119 // not really a variable, though we implement it as one. The
4086 // subexpression does not have side effects. 4120 // subexpression does not have side effects.
4087 context()->Plug(var->is_this()); 4121 context()->Plug(var->is_this());
4088 } else { 4122 } else {
4089 // Non-global variable. Call the runtime to try to delete from the 4123 // Non-global variable. Call the runtime to try to delete from the
4090 // context where the variable was introduced. 4124 // context where the variable was introduced.
4091 __ push(context_register()); 4125 AsmPush(context_register());
4092 __ push(Immediate(var->name())); 4126 AsmPushHandle(var->name());
4093 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); 4127 AsmCallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
4094 context()->Plug(eax); 4128 context()->Plug(eax);
4095 } 4129 }
4096 } else { 4130 } else {
4097 // Result of deleting non-property, non-variable reference is true. 4131 // Result of deleting non-property, non-variable reference is true.
4098 // The subexpression may have side effects. 4132 // The subexpression may have side effects.
4099 VisitForEffect(expr->expression()); 4133 VisitForEffect(expr->expression());
4100 context()->Plug(true); 4134 context()->Plug(true);
4101 } 4135 }
4102 break; 4136 break;
4103 } 4137 }
(...skipping 23 matching lines...) Expand all
4127 // We handle value contexts explicitly rather than simply visiting 4161 // We handle value contexts explicitly rather than simply visiting
4128 // for control and plugging the control flow into the context, 4162 // for control and plugging the control flow into the context,
4129 // because we need to prepare a pair of extra administrative AST ids 4163 // because we need to prepare a pair of extra administrative AST ids
4130 // for the optimizing compiler. 4164 // for the optimizing compiler.
4131 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); 4165 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
4132 Label materialize_true, materialize_false, done; 4166 Label materialize_true, materialize_false, done;
4133 VisitForControl(expr->expression(), 4167 VisitForControl(expr->expression(),
4134 &materialize_false, 4168 &materialize_false,
4135 &materialize_true, 4169 &materialize_true,
4136 &materialize_true); 4170 &materialize_true);
4171 StackHeightWrapper branch_stack_height = CurrentStackHeight();
4137 __ bind(&materialize_true); 4172 __ bind(&materialize_true);
4138 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 4173 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4139 if (context()->IsAccumulatorValue()) { 4174 if (context()->IsAccumulatorValue()) {
4140 __ mov(eax, isolate()->factory()->true_value()); 4175 __ mov(eax, isolate()->factory()->true_value());
4141 } else { 4176 } else {
4142 __ Push(isolate()->factory()->true_value()); 4177 AsmPushHandle(isolate()->factory()->true_value());
4143 } 4178 }
4144 __ jmp(&done, Label::kNear); 4179 __ jmp(&done, Label::kNear);
4145 __ bind(&materialize_false); 4180 __ bind(&materialize_false);
4181 SetStackHeight(branch_stack_height);
4146 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 4182 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
4147 if (context()->IsAccumulatorValue()) { 4183 if (context()->IsAccumulatorValue()) {
4148 __ mov(eax, isolate()->factory()->false_value()); 4184 __ mov(eax, isolate()->factory()->false_value());
4149 } else { 4185 } else {
4150 __ Push(isolate()->factory()->false_value()); 4186 AsmPushHandle(isolate()->factory()->false_value());
4151 } 4187 }
4152 __ bind(&done); 4188 __ bind(&done);
4153 } 4189 }
4154 break; 4190 break;
4155 } 4191 }
4156 4192
4157 case Token::TYPEOF: { 4193 case Token::TYPEOF: {
4158 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 4194 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
4159 { StackValueContext context(this); 4195 { StackValueContext context(this);
4160 VisitForTypeofValue(expr->expression()); 4196 VisitForTypeofValue(expr->expression());
4161 } 4197 }
4162 __ CallRuntime(Runtime::kTypeof, 1); 4198 AsmCallRuntime(Runtime::kTypeof, 1);
4163 context()->Plug(eax); 4199 context()->Plug(eax);
4164 break; 4200 break;
4165 } 4201 }
4166 4202
4167 default: 4203 default:
4168 UNREACHABLE(); 4204 UNREACHABLE();
4169 } 4205 }
4170 } 4206 }
4171 4207
4172 4208
(...skipping 16 matching lines...) Expand all
4189 } 4225 }
4190 4226
4191 // Evaluate expression and get value. 4227 // Evaluate expression and get value.
4192 if (assign_type == VARIABLE) { 4228 if (assign_type == VARIABLE) {
4193 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 4229 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
4194 AccumulatorValueContext context(this); 4230 AccumulatorValueContext context(this);
4195 EmitVariableLoad(expr->expression()->AsVariableProxy()); 4231 EmitVariableLoad(expr->expression()->AsVariableProxy());
4196 } else { 4232 } else {
4197 // Reserve space for result of postfix operation. 4233 // Reserve space for result of postfix operation.
4198 if (expr->is_postfix() && !context()->IsEffect()) { 4234 if (expr->is_postfix() && !context()->IsEffect()) {
4199 __ push(Immediate(Smi::FromInt(0))); 4235 AsmPushSmi(Smi::FromInt(0));
4200 } 4236 }
4201 if (assign_type == NAMED_PROPERTY) { 4237 if (assign_type == NAMED_PROPERTY) {
4202 // Put the object both on the stack and in edx. 4238 // Put the object both on the stack and in edx.
4203 VisitForAccumulatorValue(prop->obj()); 4239 VisitForAccumulatorValue(prop->obj());
4204 __ push(eax); 4240 AsmPush(eax);
4205 __ mov(edx, eax); 4241 __ mov(edx, eax);
4206 EmitNamedPropertyLoad(prop); 4242 EmitNamedPropertyLoad(prop);
4207 } else { 4243 } else {
4208 VisitForStackValue(prop->obj()); 4244 VisitForStackValue(prop->obj());
4209 VisitForStackValue(prop->key()); 4245 VisitForStackValue(prop->key());
4210 __ mov(edx, Operand(esp, kPointerSize)); // Object. 4246 __ mov(edx, Operand(esp, kPointerSize)); // Object.
4211 __ mov(ecx, Operand(esp, 0)); // Key. 4247 __ mov(ecx, Operand(esp, 0)); // Key.
4212 EmitKeyedPropertyLoad(prop); 4248 EmitKeyedPropertyLoad(prop);
4213 } 4249 }
4214 } 4250 }
4215 4251
4216 // We need a second deoptimization point after loading the value 4252 // We need a second deoptimization point after loading the value
4217 // in case evaluating the property load my have a side effect. 4253 // in case evaluating the property load my have a side effect.
4218 if (assign_type == VARIABLE) { 4254 if (assign_type == VARIABLE) {
4219 PrepareForBailout(expr->expression(), TOS_REG); 4255 PrepareForBailout(expr->expression(), TOS_REG);
4220 } else { 4256 } else {
4221 PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4257 PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4222 } 4258 }
4223 4259
4224 // Inline smi case if we are in a loop. 4260 // Inline smi case if we are in a loop.
4225 Label done, stub_call; 4261 Label done, stub_call;
4226 JumpPatchSite patch_site(masm_); 4262 JumpPatchSite patch_site(masm_);
4227 if (ShouldInlineSmiCase(expr->op())) { 4263 if (ShouldInlineSmiCase(expr->op())) {
4228 Label slow; 4264 Label slow;
4229 patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear); 4265 patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear);
4230 4266
4267 StackHeightWrapper smi_stack_height = CurrentStackHeight();
4268
4231 // Save result for postfix expressions. 4269 // Save result for postfix expressions.
4232 if (expr->is_postfix()) { 4270 if (expr->is_postfix()) {
4233 if (!context()->IsEffect()) { 4271 if (!context()->IsEffect()) {
4234 // Save the result on the stack. If we have a named or keyed property 4272 // Save the result on the stack. If we have a named or keyed property
4235 // we store the result under the receiver that is currently on top 4273 // we store the result under the receiver that is currently on top
4236 // of the stack. 4274 // of the stack.
4237 switch (assign_type) { 4275 switch (assign_type) {
4238 case VARIABLE: 4276 case VARIABLE:
4239 __ push(eax); 4277 AsmPush(eax);
4240 break; 4278 break;
4241 case NAMED_PROPERTY: 4279 case NAMED_PROPERTY:
4242 __ mov(Operand(esp, kPointerSize), eax); 4280 __ mov(Operand(esp, kPointerSize), eax);
4243 break; 4281 break;
4244 case KEYED_PROPERTY: 4282 case KEYED_PROPERTY:
4245 __ mov(Operand(esp, 2 * kPointerSize), eax); 4283 __ mov(Operand(esp, 2 * kPointerSize), eax);
4246 break; 4284 break;
4247 } 4285 }
4248 } 4286 }
4249 } 4287 }
4250 4288
4251 if (expr->op() == Token::INC) { 4289 if (expr->op() == Token::INC) {
4252 __ add(eax, Immediate(Smi::FromInt(1))); 4290 __ add(eax, Immediate(Smi::FromInt(1)));
4253 } else { 4291 } else {
4254 __ sub(eax, Immediate(Smi::FromInt(1))); 4292 __ sub(eax, Immediate(Smi::FromInt(1)));
4255 } 4293 }
4256 __ j(no_overflow, &done, Label::kNear); 4294 __ j(no_overflow, &done, Label::kNear);
4257 // Call stub. Undo operation first. 4295 // Call stub. Undo operation first.
4258 if (expr->op() == Token::INC) { 4296 if (expr->op() == Token::INC) {
4259 __ sub(eax, Immediate(Smi::FromInt(1))); 4297 __ sub(eax, Immediate(Smi::FromInt(1)));
4260 } else { 4298 } else {
4261 __ add(eax, Immediate(Smi::FromInt(1))); 4299 __ add(eax, Immediate(Smi::FromInt(1)));
4262 } 4300 }
4263 __ jmp(&stub_call, Label::kNear); 4301 __ jmp(&stub_call, Label::kNear);
4264 __ bind(&slow); 4302 __ bind(&slow);
4303 SetStackHeight(smi_stack_height);
4265 } 4304 }
4266 ToNumberStub convert_stub(isolate()); 4305 ToNumberStub convert_stub(isolate());
4267 __ CallStub(&convert_stub); 4306 __ CallStub(&convert_stub);
4268 4307
4269 // Save result for postfix expressions. 4308 // Save result for postfix expressions.
4270 if (expr->is_postfix()) { 4309 if (expr->is_postfix()) {
4271 if (!context()->IsEffect()) { 4310 if (!context()->IsEffect()) {
4272 // Save the result on the stack. If we have a named or keyed property 4311 // Save the result on the stack. If we have a named or keyed property
4273 // we store the result under the receiver that is currently on top 4312 // we store the result under the receiver that is currently on top
4274 // of the stack. 4313 // of the stack.
4275 switch (assign_type) { 4314 switch (assign_type) {
4276 case VARIABLE: 4315 case VARIABLE:
4277 __ push(eax); 4316 AsmPush(eax);
4278 break; 4317 break;
4279 case NAMED_PROPERTY: 4318 case NAMED_PROPERTY:
4280 __ mov(Operand(esp, kPointerSize), eax); 4319 __ mov(Operand(esp, kPointerSize), eax);
4281 break; 4320 break;
4282 case KEYED_PROPERTY: 4321 case KEYED_PROPERTY:
4283 __ mov(Operand(esp, 2 * kPointerSize), eax); 4322 __ mov(Operand(esp, 2 * kPointerSize), eax);
4284 break; 4323 break;
4285 } 4324 }
4286 } 4325 }
4287 } 4326 }
(...skipping 29 matching lines...) Expand all
4317 } else { 4356 } else {
4318 // Perform the assignment as if via '='. 4357 // Perform the assignment as if via '='.
4319 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4358 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4320 Token::ASSIGN); 4359 Token::ASSIGN);
4321 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4360 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4322 context()->Plug(eax); 4361 context()->Plug(eax);
4323 } 4362 }
4324 break; 4363 break;
4325 case NAMED_PROPERTY: { 4364 case NAMED_PROPERTY: {
4326 __ mov(ecx, prop->key()->AsLiteral()->value()); 4365 __ mov(ecx, prop->key()->AsLiteral()->value());
4327 __ pop(edx); 4366 AsmPop(edx);
4328 CallStoreIC(expr->CountStoreFeedbackId()); 4367 CallStoreIC(expr->CountStoreFeedbackId());
4329 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4368 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4330 if (expr->is_postfix()) { 4369 if (expr->is_postfix()) {
4331 if (!context()->IsEffect()) { 4370 if (!context()->IsEffect()) {
4332 context()->PlugTOS(); 4371 context()->PlugTOS();
4333 } 4372 }
4334 } else { 4373 } else {
4335 context()->Plug(eax); 4374 context()->Plug(eax);
4336 } 4375 }
4337 break; 4376 break;
4338 } 4377 }
4339 case KEYED_PROPERTY: { 4378 case KEYED_PROPERTY: {
4340 __ pop(ecx); 4379 AsmPop(ecx);
4341 __ pop(edx); 4380 AsmPop(edx);
4342 Handle<Code> ic = strict_mode() == SLOPPY 4381 Handle<Code> ic = strict_mode() == SLOPPY
4343 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4382 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4344 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4383 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4345 CallIC(ic, expr->CountStoreFeedbackId()); 4384 CallIC(ic, expr->CountStoreFeedbackId());
4346 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4385 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4347 if (expr->is_postfix()) { 4386 if (expr->is_postfix()) {
4348 // Result is on the stack 4387 // Result is on the stack
4349 if (!context()->IsEffect()) { 4388 if (!context()->IsEffect()) {
4350 context()->PlugTOS(); 4389 context()->PlugTOS();
4351 } 4390 }
(...skipping 22 matching lines...) Expand all
4374 context()->Plug(eax); 4413 context()->Plug(eax);
4375 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4414 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4376 Comment cmnt(masm_, "[ Lookup slot"); 4415 Comment cmnt(masm_, "[ Lookup slot");
4377 Label done, slow; 4416 Label done, slow;
4378 4417
4379 // Generate code for loading from variables potentially shadowed 4418 // Generate code for loading from variables potentially shadowed
4380 // by eval-introduced variables. 4419 // by eval-introduced variables.
4381 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4420 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4382 4421
4383 __ bind(&slow); 4422 __ bind(&slow);
4384 __ push(esi); 4423 AsmPush(esi);
4385 __ push(Immediate(proxy->name())); 4424 AsmPushHandle(proxy->name());
4386 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); 4425 AsmCallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
4387 PrepareForBailout(expr, TOS_REG); 4426 PrepareForBailout(expr, TOS_REG);
4388 __ bind(&done); 4427 __ bind(&done);
4389 4428
4390 context()->Plug(eax); 4429 context()->Plug(eax);
4391 } else { 4430 } else {
4392 // This expression cannot throw a reference error at the top level. 4431 // This expression cannot throw a reference error at the top level.
4393 VisitInDuplicateContext(expr); 4432 VisitInDuplicateContext(expr);
4394 } 4433 }
4395 } 4434 }
4396 4435
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
4489 Label* if_false = NULL; 4528 Label* if_false = NULL;
4490 Label* fall_through = NULL; 4529 Label* fall_through = NULL;
4491 context()->PrepareTest(&materialize_true, &materialize_false, 4530 context()->PrepareTest(&materialize_true, &materialize_false,
4492 &if_true, &if_false, &fall_through); 4531 &if_true, &if_false, &fall_through);
4493 4532
4494 Token::Value op = expr->op(); 4533 Token::Value op = expr->op();
4495 VisitForStackValue(expr->left()); 4534 VisitForStackValue(expr->left());
4496 switch (op) { 4535 switch (op) {
4497 case Token::IN: 4536 case Token::IN:
4498 VisitForStackValue(expr->right()); 4537 VisitForStackValue(expr->right());
4499 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4538 AsmInvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
4500 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4539 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4501 __ cmp(eax, isolate()->factory()->true_value()); 4540 __ cmp(eax, isolate()->factory()->true_value());
4502 Split(equal, if_true, if_false, fall_through); 4541 Split(equal, if_true, if_false, fall_through);
4503 break; 4542 break;
4504 4543
4505 case Token::INSTANCEOF: { 4544 case Token::INSTANCEOF: {
4506 VisitForStackValue(expr->right()); 4545 VisitForStackValue(expr->right());
4507 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); 4546 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4508 __ CallStub(&stub); 4547 AsmCallStub(&stub, 2);
4509 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4548 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4510 __ test(eax, eax); 4549 __ test(eax, eax);
4511 // The stub returns 0 for true. 4550 // The stub returns 0 for true.
4512 Split(zero, if_true, if_false, fall_through); 4551 Split(zero, if_true, if_false, fall_through);
4513 break; 4552 break;
4514 } 4553 }
4515 4554
4516 default: { 4555 default: {
4517 VisitForAccumulatorValue(expr->right()); 4556 VisitForAccumulatorValue(expr->right());
4518 Condition cc = CompareIC::ComputeCondition(op); 4557 Condition cc = CompareIC::ComputeCondition(op);
4519 __ pop(edx); 4558 AsmPop(edx);
4520 4559
4521 bool inline_smi_code = ShouldInlineSmiCase(op); 4560 bool inline_smi_code = ShouldInlineSmiCase(op);
4522 JumpPatchSite patch_site(masm_); 4561 JumpPatchSite patch_site(masm_);
4523 if (inline_smi_code) { 4562 if (inline_smi_code) {
4524 Label slow_case; 4563 Label slow_case;
4525 __ mov(ecx, edx); 4564 __ mov(ecx, edx);
4526 __ or_(ecx, eax); 4565 __ or_(ecx, eax);
4527 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4566 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4528 __ cmp(edx, eax); 4567 __ cmp(edx, eax);
4529 Split(cc, if_true, if_false, NULL); 4568 Split(cc, if_true, if_false, NULL);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
4605 4644
4606 4645
4607 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4646 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4608 Scope* declaration_scope = scope()->DeclarationScope(); 4647 Scope* declaration_scope = scope()->DeclarationScope();
4609 if (declaration_scope->is_global_scope() || 4648 if (declaration_scope->is_global_scope() ||
4610 declaration_scope->is_module_scope()) { 4649 declaration_scope->is_module_scope()) {
4611 // Contexts nested in the native context have a canonical empty function 4650 // Contexts nested in the native context have a canonical empty function
4612 // as their closure, not the anonymous closure containing the global 4651 // as their closure, not the anonymous closure containing the global
4613 // code. Pass a smi sentinel and let the runtime look up the empty 4652 // code. Pass a smi sentinel and let the runtime look up the empty
4614 // function. 4653 // function.
4615 __ push(Immediate(Smi::FromInt(0))); 4654 AsmPushSmi(Smi::FromInt(0));
4616 } else if (declaration_scope->is_eval_scope()) { 4655 } else if (declaration_scope->is_eval_scope()) {
4617 // Contexts nested inside eval code have the same closure as the context 4656 // Contexts nested inside eval code have the same closure as the context
4618 // calling eval, not the anonymous closure containing the eval code. 4657 // calling eval, not the anonymous closure containing the eval code.
4619 // Fetch it from the context. 4658 // Fetch it from the context.
4620 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); 4659 AsmPush(ContextOperand(esi, Context::CLOSURE_INDEX));
4621 } else { 4660 } else {
4622 ASSERT(declaration_scope->is_function_scope()); 4661 ASSERT(declaration_scope->is_function_scope());
4623 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4662 AsmPush(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4624 } 4663 }
4625 } 4664 }
4626 4665
4627 4666
4628 // ---------------------------------------------------------------------------- 4667 // ----------------------------------------------------------------------------
4629 // Non-local control flow support. 4668 // Non-local control flow support.
4630 4669
4631 void FullCodeGenerator::EnterFinallyBlock() { 4670 void FullCodeGenerator::EnterFinallyBlock() {
4632 // Cook return address on top of stack (smi encoded Code* delta) 4671 // Cook return address on top of stack (smi encoded Code* delta)
4633 ASSERT(!result_register().is(edx)); 4672 ASSERT(!result_register().is(edx));
4634 __ pop(edx); 4673 AsmPop(edx);
4635 __ sub(edx, Immediate(masm_->CodeObject())); 4674 __ sub(edx, Immediate(masm_->CodeObject()));
4636 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4675 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4637 STATIC_ASSERT(kSmiTag == 0); 4676 STATIC_ASSERT(kSmiTag == 0);
4638 __ SmiTag(edx); 4677 __ SmiTag(edx);
4639 __ push(edx); 4678 AsmPush(edx);
4640 4679
4641 // Store result register while executing finally block. 4680 // Store result register while executing finally block.
4642 __ push(result_register()); 4681 AsmPush(result_register());
4643 4682
4644 // Store pending message while executing finally block. 4683 // Store pending message while executing finally block.
4645 ExternalReference pending_message_obj = 4684 ExternalReference pending_message_obj =
4646 ExternalReference::address_of_pending_message_obj(isolate()); 4685 ExternalReference::address_of_pending_message_obj(isolate());
4647 __ mov(edx, Operand::StaticVariable(pending_message_obj)); 4686 __ mov(edx, Operand::StaticVariable(pending_message_obj));
4648 __ push(edx); 4687 AsmPush(edx);
4649 4688
4650 ExternalReference has_pending_message = 4689 ExternalReference has_pending_message =
4651 ExternalReference::address_of_has_pending_message(isolate()); 4690 ExternalReference::address_of_has_pending_message(isolate());
4652 __ mov(edx, Operand::StaticVariable(has_pending_message)); 4691 __ mov(edx, Operand::StaticVariable(has_pending_message));
4653 __ SmiTag(edx); 4692 __ SmiTag(edx);
4654 __ push(edx); 4693 AsmPush(edx);
4655 4694
4656 ExternalReference pending_message_script = 4695 ExternalReference pending_message_script =
4657 ExternalReference::address_of_pending_message_script(isolate()); 4696 ExternalReference::address_of_pending_message_script(isolate());
4658 __ mov(edx, Operand::StaticVariable(pending_message_script)); 4697 __ mov(edx, Operand::StaticVariable(pending_message_script));
4659 __ push(edx); 4698 AsmPush(edx);
4660 } 4699 }
4661 4700
4662 4701
4663 void FullCodeGenerator::ExitFinallyBlock() { 4702 void FullCodeGenerator::ExitFinallyBlock() {
4664 ASSERT(!result_register().is(edx)); 4703 ASSERT(!result_register().is(edx));
4665 // Restore pending message from stack. 4704 // Restore pending message from stack.
4666 __ pop(edx); 4705 AsmPop(edx);
4667 ExternalReference pending_message_script = 4706 ExternalReference pending_message_script =
4668 ExternalReference::address_of_pending_message_script(isolate()); 4707 ExternalReference::address_of_pending_message_script(isolate());
4669 __ mov(Operand::StaticVariable(pending_message_script), edx); 4708 __ mov(Operand::StaticVariable(pending_message_script), edx);
4670 4709
4671 __ pop(edx); 4710 AsmPop(edx);
4672 __ SmiUntag(edx); 4711 __ SmiUntag(edx);
4673 ExternalReference has_pending_message = 4712 ExternalReference has_pending_message =
4674 ExternalReference::address_of_has_pending_message(isolate()); 4713 ExternalReference::address_of_has_pending_message(isolate());
4675 __ mov(Operand::StaticVariable(has_pending_message), edx); 4714 __ mov(Operand::StaticVariable(has_pending_message), edx);
4676 4715
4677 __ pop(edx); 4716 AsmPop(edx);
4678 ExternalReference pending_message_obj = 4717 ExternalReference pending_message_obj =
4679 ExternalReference::address_of_pending_message_obj(isolate()); 4718 ExternalReference::address_of_pending_message_obj(isolate());
4680 __ mov(Operand::StaticVariable(pending_message_obj), edx); 4719 __ mov(Operand::StaticVariable(pending_message_obj), edx);
4681 4720
4682 // Restore result register from stack. 4721 // Restore result register from stack.
4683 __ pop(result_register()); 4722 AsmPop(result_register());
4684 4723
4685 // Uncook return address. 4724 // Uncook return address.
4686 __ pop(edx); 4725 AsmPop(edx);
4687 __ SmiUntag(edx); 4726 __ SmiUntag(edx);
4688 __ add(edx, Immediate(masm_->CodeObject())); 4727 __ add(edx, Immediate(masm_->CodeObject()));
4689 __ jmp(edx); 4728 __ jmp(edx);
4690 } 4729 }
4691 4730
4692 4731
4732 #if defined(VERIFY_STACK_HEIGHT)
4733 void FullCodeGenerator::AddStackHeightVerifier() {
4734 // Insert code that verifies at runtime that our stack height calculation
4735 // is correct
4736 Label L;
4737 __ push(eax);
4738 __ pushfd();
4739 __ mov(eax, ebp);
4740 __ sub(eax, esp);
4741 const int stack_diff = 4; // We need to account for the pushed stuff
4742 __ cmp(eax, (stack_height_.get() + stack_diff) * kPointerSize);
4743 __ j(equal, &L);
4744 __ int3();
4745 __ bind(&L);
4746 __ popfd();
4747 __ pop(eax);
4748 }
4749 #endif // defined(VERIFY_STACK_HEIGHT)
4750
4751 void FullCodeGenerator::AsmPush(const Operand& op) {
4752 masm()->push(op);
4753 UpdateStackHeight(1);
4754 }
4755
4756
4693 #undef __ 4757 #undef __
4694 4758
4695 #define __ ACCESS_MASM(masm()) 4759 #define __ ACCESS_MASM(masm())
4696 4760
4697 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4761 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4698 int* stack_depth, 4762 int* stack_depth,
4699 int* context_length) { 4763 int* context_length) {
4700 // The macros used here must preserve the result register. 4764 // The macros used here must preserve the result register.
4701 4765
4702 // Because the handler block contains the context of the finally 4766 // Because the handler block contains the context of the finally
4703 // code, we can restore it directly from there for the finally code 4767 // code, we can restore it directly from there for the finally code
4704 // rather than iteratively unwinding contexts via their previous 4768 // rather than iteratively unwinding contexts via their previous
4705 // links. 4769 // links.
4706 __ Drop(*stack_depth); // Down to the handler block. 4770 codegen()->AsmDrop(*stack_depth); // Down to the handler block.
4707 if (*context_length > 0) { 4771 if (*context_length > 0) {
4708 // Restore the context to its dedicated register and the stack. 4772 // Restore the context to its dedicated register and the stack.
4709 __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset)); 4773 __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
4710 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 4774 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
4711 } 4775 }
4712 __ PopTryHandler(); 4776 codegen()->AsmPopTryHandler();
4713 __ call(finally_entry_); 4777 __ call(finally_entry_);
4714 4778
4715 *stack_depth = 0; 4779 *stack_depth = 0;
4716 *context_length = 0; 4780 *context_length = 0;
4717 return previous_; 4781 return previous_;
4718 } 4782 }
4719 4783
4720 #undef __ 4784 #undef __
4721 4785
4722
4723 static const byte kJnsInstruction = 0x79; 4786 static const byte kJnsInstruction = 0x79;
4724 static const byte kJnsOffset = 0x11; 4787 static const byte kJnsOffset = 0x11;
4725 static const byte kNopByteOne = 0x66; 4788 static const byte kNopByteOne = 0x66;
4726 static const byte kNopByteTwo = 0x90; 4789 static const byte kNopByteTwo = 0x90;
4727 #ifdef DEBUG 4790 #ifdef DEBUG
4728 static const byte kCallInstruction = 0xe8; 4791 static const byte kCallInstruction = 0xe8;
4729 #endif 4792 #endif
4730 4793
4731 4794
4732 void BackEdgeTable::PatchAt(Code* unoptimized_code, 4795 void BackEdgeTable::PatchAt(Code* unoptimized_code,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4793 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4856 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4794 Assembler::target_address_at(call_target_address, 4857 Assembler::target_address_at(call_target_address,
4795 unoptimized_code)); 4858 unoptimized_code));
4796 return OSR_AFTER_STACK_CHECK; 4859 return OSR_AFTER_STACK_CHECK;
4797 } 4860 }
4798 4861
4799 4862
4800 } } // namespace v8::internal 4863 } } // namespace v8::internal
4801 4864
4802 #endif // V8_TARGET_ARCH_IA32 4865 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698