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

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

Issue 430503007: Rename ASSERT* to DCHECK*. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE and fixes Created 6 years, 4 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/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('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 "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 13 matching lines...) Expand all
24 24
25 class JumpPatchSite BASE_EMBEDDED { 25 class JumpPatchSite BASE_EMBEDDED {
26 public: 26 public:
27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
28 #ifdef DEBUG 28 #ifdef DEBUG
29 info_emitted_ = false; 29 info_emitted_ = false;
30 #endif 30 #endif
31 } 31 }
32 32
33 ~JumpPatchSite() { 33 ~JumpPatchSite() {
34 ASSERT(patch_site_.is_bound() == info_emitted_); 34 DCHECK(patch_site_.is_bound() == info_emitted_);
35 } 35 }
36 36
37 void EmitJumpIfNotSmi(Register reg, 37 void EmitJumpIfNotSmi(Register reg,
38 Label* target, 38 Label* target,
39 Label::Distance distance = Label::kFar) { 39 Label::Distance distance = Label::kFar) {
40 __ test(reg, Immediate(kSmiTagMask)); 40 __ test(reg, Immediate(kSmiTagMask));
41 EmitJump(not_carry, target, distance); // Always taken before patched. 41 EmitJump(not_carry, target, distance); // Always taken before patched.
42 } 42 }
43 43
44 void EmitJumpIfSmi(Register reg, 44 void EmitJumpIfSmi(Register reg,
45 Label* target, 45 Label* target,
46 Label::Distance distance = Label::kFar) { 46 Label::Distance distance = Label::kFar) {
47 __ test(reg, Immediate(kSmiTagMask)); 47 __ test(reg, Immediate(kSmiTagMask));
48 EmitJump(carry, target, distance); // Never taken before patched. 48 EmitJump(carry, target, distance); // Never taken before patched.
49 } 49 }
50 50
51 void EmitPatchInfo() { 51 void EmitPatchInfo() {
52 if (patch_site_.is_bound()) { 52 if (patch_site_.is_bound()) {
53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
54 ASSERT(is_uint8(delta_to_patch_site)); 54 DCHECK(is_uint8(delta_to_patch_site));
55 __ test(eax, Immediate(delta_to_patch_site)); 55 __ test(eax, Immediate(delta_to_patch_site));
56 #ifdef DEBUG 56 #ifdef DEBUG
57 info_emitted_ = true; 57 info_emitted_ = true;
58 #endif 58 #endif
59 } else { 59 } else {
60 __ nop(); // Signals no inlined code. 60 __ nop(); // Signals no inlined code.
61 } 61 }
62 } 62 }
63 63
64 private: 64 private:
65 // jc will be patched with jz, jnc will become jnz. 65 // jc will be patched with jz, jnc will become jnz.
66 void EmitJump(Condition cc, Label* target, Label::Distance distance) { 66 void EmitJump(Condition cc, Label* target, Label::Distance distance) {
67 ASSERT(!patch_site_.is_bound() && !info_emitted_); 67 DCHECK(!patch_site_.is_bound() && !info_emitted_);
68 ASSERT(cc == carry || cc == not_carry); 68 DCHECK(cc == carry || cc == not_carry);
69 __ bind(&patch_site_); 69 __ bind(&patch_site_);
70 __ j(cc, target, distance); 70 __ j(cc, target, distance);
71 } 71 }
72 72
73 MacroAssembler* masm_; 73 MacroAssembler* masm_;
74 Label patch_site_; 74 Label patch_site_;
75 #ifdef DEBUG 75 #ifdef DEBUG
76 bool info_emitted_; 76 bool info_emitted_;
77 #endif 77 #endif
78 }; 78 };
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // the frame (that is done below). 135 // the frame (that is done below).
136 FrameScope frame_scope(masm_, StackFrame::MANUAL); 136 FrameScope frame_scope(masm_, StackFrame::MANUAL);
137 137
138 info->set_prologue_offset(masm_->pc_offset()); 138 info->set_prologue_offset(masm_->pc_offset());
139 __ Prologue(info->IsCodePreAgingActive()); 139 __ Prologue(info->IsCodePreAgingActive());
140 info->AddNoFrameRange(0, masm_->pc_offset()); 140 info->AddNoFrameRange(0, masm_->pc_offset());
141 141
142 { Comment cmnt(masm_, "[ Allocate locals"); 142 { Comment cmnt(masm_, "[ Allocate locals");
143 int locals_count = info->scope()->num_stack_slots(); 143 int locals_count = info->scope()->num_stack_slots();
144 // Generators allocate locals, if any, in context slots. 144 // Generators allocate locals, if any, in context slots.
145 ASSERT(!info->function()->is_generator() || locals_count == 0); 145 DCHECK(!info->function()->is_generator() || locals_count == 0);
146 if (locals_count == 1) { 146 if (locals_count == 1) {
147 __ push(Immediate(isolate()->factory()->undefined_value())); 147 __ push(Immediate(isolate()->factory()->undefined_value()));
148 } else if (locals_count > 1) { 148 } else if (locals_count > 1) {
149 if (locals_count >= 128) { 149 if (locals_count >= 128) {
150 Label ok; 150 Label ok;
151 __ mov(ecx, esp); 151 __ mov(ecx, esp);
152 __ sub(ecx, Immediate(locals_count * kPointerSize)); 152 __ sub(ecx, Immediate(locals_count * kPointerSize));
153 ExternalReference stack_limit = 153 ExternalReference stack_limit =
154 ExternalReference::address_of_real_stack_limit(isolate()); 154 ExternalReference::address_of_real_stack_limit(isolate());
155 __ cmp(ecx, Operand::StaticVariable(stack_limit)); 155 __ cmp(ecx, Operand::StaticVariable(stack_limit));
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 Comment cmnt(masm_, "[ Declarations"); 279 Comment cmnt(masm_, "[ Declarations");
280 scope()->VisitIllegalRedeclaration(this); 280 scope()->VisitIllegalRedeclaration(this);
281 281
282 } else { 282 } else {
283 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 283 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
284 { Comment cmnt(masm_, "[ Declarations"); 284 { Comment cmnt(masm_, "[ Declarations");
285 // For named function expressions, declare the function name as a 285 // For named function expressions, declare the function name as a
286 // constant. 286 // constant.
287 if (scope()->is_function_scope() && scope()->function() != NULL) { 287 if (scope()->is_function_scope() && scope()->function() != NULL) {
288 VariableDeclaration* function = scope()->function(); 288 VariableDeclaration* function = scope()->function();
289 ASSERT(function->proxy()->var()->mode() == CONST || 289 DCHECK(function->proxy()->var()->mode() == CONST ||
290 function->proxy()->var()->mode() == CONST_LEGACY); 290 function->proxy()->var()->mode() == CONST_LEGACY);
291 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); 291 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
292 VisitVariableDeclaration(function); 292 VisitVariableDeclaration(function);
293 } 293 }
294 VisitDeclarations(scope()->declarations()); 294 VisitDeclarations(scope()->declarations());
295 } 295 }
296 296
297 { Comment cmnt(masm_, "[ Stack check"); 297 { Comment cmnt(masm_, "[ Stack check");
298 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 298 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
299 Label ok; 299 Label ok;
300 ExternalReference stack_limit 300 ExternalReference stack_limit
301 = ExternalReference::address_of_stack_limit(isolate()); 301 = ExternalReference::address_of_stack_limit(isolate());
302 __ cmp(esp, Operand::StaticVariable(stack_limit)); 302 __ cmp(esp, Operand::StaticVariable(stack_limit));
303 __ j(above_equal, &ok, Label::kNear); 303 __ j(above_equal, &ok, Label::kNear);
304 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); 304 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
305 __ bind(&ok); 305 __ bind(&ok);
306 } 306 }
307 307
308 { Comment cmnt(masm_, "[ Body"); 308 { Comment cmnt(masm_, "[ Body");
309 ASSERT(loop_depth() == 0); 309 DCHECK(loop_depth() == 0);
310 VisitStatements(function()->body()); 310 VisitStatements(function()->body());
311 ASSERT(loop_depth() == 0); 311 DCHECK(loop_depth() == 0);
312 } 312 }
313 } 313 }
314 314
315 // Always emit a 'return undefined' in case control fell off the end of 315 // Always emit a 'return undefined' in case control fell off the end of
316 // the body. 316 // the body.
317 { Comment cmnt(masm_, "[ return <undefined>;"); 317 { Comment cmnt(masm_, "[ return <undefined>;");
318 __ mov(eax, isolate()->factory()->undefined_value()); 318 __ mov(eax, isolate()->factory()->undefined_value());
319 EmitReturnSequence(); 319 EmitReturnSequence();
320 } 320 }
321 } 321 }
(...skipping 17 matching lines...) Expand all
339 __ mov(FieldOperand(ebx, Cell::kValueOffset), 339 __ mov(FieldOperand(ebx, Cell::kValueOffset),
340 Immediate(Smi::FromInt(reset_value))); 340 Immediate(Smi::FromInt(reset_value)));
341 } 341 }
342 342
343 343
344 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 344 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
345 Label* back_edge_target) { 345 Label* back_edge_target) {
346 Comment cmnt(masm_, "[ Back edge bookkeeping"); 346 Comment cmnt(masm_, "[ Back edge bookkeeping");
347 Label ok; 347 Label ok;
348 348
349 ASSERT(back_edge_target->is_bound()); 349 DCHECK(back_edge_target->is_bound());
350 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 350 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
351 int weight = Min(kMaxBackEdgeWeight, 351 int weight = Min(kMaxBackEdgeWeight,
352 Max(1, distance / kCodeSizeMultiplier)); 352 Max(1, distance / kCodeSizeMultiplier));
353 EmitProfilingCounterDecrement(weight); 353 EmitProfilingCounterDecrement(weight);
354 __ j(positive, &ok, Label::kNear); 354 __ j(positive, &ok, Label::kNear);
355 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 355 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
356 356
357 // Record a mapping of this PC offset to the OSR id. This is used to find 357 // Record a mapping of this PC offset to the OSR id. This is used to find
358 // the AST id from the unoptimized code in order to use it as a key into 358 // the AST id from the unoptimized code in order to use it as a key into
359 // the deoptimization input data found in the optimized code. 359 // the deoptimization input data found in the optimized code.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 // Do not use the leave instruction here because it is too short to 409 // Do not use the leave instruction here because it is too short to
410 // patch with the code required by the debugger. 410 // patch with the code required by the debugger.
411 __ mov(esp, ebp); 411 __ mov(esp, ebp);
412 int no_frame_start = masm_->pc_offset(); 412 int no_frame_start = masm_->pc_offset();
413 __ pop(ebp); 413 __ pop(ebp);
414 414
415 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; 415 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
416 __ Ret(arguments_bytes, ecx); 416 __ Ret(arguments_bytes, ecx);
417 // Check that the size of the code used for returning is large enough 417 // Check that the size of the code used for returning is large enough
418 // for the debugger's requirements. 418 // for the debugger's requirements.
419 ASSERT(Assembler::kJSReturnSequenceLength <= 419 DCHECK(Assembler::kJSReturnSequenceLength <=
420 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 420 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
421 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 421 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
422 } 422 }
423 } 423 }
424 424
425 425
426 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { 426 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
427 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 427 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
428 } 428 }
429 429
430 430
431 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 431 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
432 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 432 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
433 codegen()->GetVar(result_register(), var); 433 codegen()->GetVar(result_register(), var);
434 } 434 }
435 435
436 436
437 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 437 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
438 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 438 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
439 MemOperand operand = codegen()->VarOperand(var, result_register()); 439 MemOperand operand = codegen()->VarOperand(var, result_register());
440 // Memory operands can be pushed directly. 440 // Memory operands can be pushed directly.
441 __ push(operand); 441 __ push(operand);
442 } 442 }
443 443
444 444
445 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 445 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
446 // For simplicity we always test the accumulator register. 446 // For simplicity we always test the accumulator register.
447 codegen()->GetVar(result_register(), var); 447 codegen()->GetVar(result_register(), var);
448 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 448 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 __ push(Immediate(lit)); 493 __ push(Immediate(lit));
494 } 494 }
495 } 495 }
496 496
497 497
498 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 498 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
499 codegen()->PrepareForBailoutBeforeSplit(condition(), 499 codegen()->PrepareForBailoutBeforeSplit(condition(),
500 true, 500 true,
501 true_label_, 501 true_label_,
502 false_label_); 502 false_label_);
503 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 503 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals.
504 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 504 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
505 if (false_label_ != fall_through_) __ jmp(false_label_); 505 if (false_label_ != fall_through_) __ jmp(false_label_);
506 } else if (lit->IsTrue() || lit->IsJSObject()) { 506 } else if (lit->IsTrue() || lit->IsJSObject()) {
507 if (true_label_ != fall_through_) __ jmp(true_label_); 507 if (true_label_ != fall_through_) __ jmp(true_label_);
508 } else if (lit->IsString()) { 508 } else if (lit->IsString()) {
509 if (String::cast(*lit)->length() == 0) { 509 if (String::cast(*lit)->length() == 0) {
510 if (false_label_ != fall_through_) __ jmp(false_label_); 510 if (false_label_ != fall_through_) __ jmp(false_label_);
511 } else { 511 } else {
512 if (true_label_ != fall_through_) __ jmp(true_label_); 512 if (true_label_ != fall_through_) __ jmp(true_label_);
513 } 513 }
514 } else if (lit->IsSmi()) { 514 } else if (lit->IsSmi()) {
515 if (Smi::cast(*lit)->value() == 0) { 515 if (Smi::cast(*lit)->value() == 0) {
516 if (false_label_ != fall_through_) __ jmp(false_label_); 516 if (false_label_ != fall_through_) __ jmp(false_label_);
517 } else { 517 } else {
518 if (true_label_ != fall_through_) __ jmp(true_label_); 518 if (true_label_ != fall_through_) __ jmp(true_label_);
519 } 519 }
520 } else { 520 } else {
521 // For simplicity we always test the accumulator register. 521 // For simplicity we always test the accumulator register.
522 __ mov(result_register(), lit); 522 __ mov(result_register(), lit);
523 codegen()->DoTest(this); 523 codegen()->DoTest(this);
524 } 524 }
525 } 525 }
526 526
527 527
528 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 528 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
529 Register reg) const { 529 Register reg) const {
530 ASSERT(count > 0); 530 DCHECK(count > 0);
531 __ Drop(count); 531 __ Drop(count);
532 } 532 }
533 533
534 534
535 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 535 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
536 int count, 536 int count,
537 Register reg) const { 537 Register reg) const {
538 ASSERT(count > 0); 538 DCHECK(count > 0);
539 __ Drop(count); 539 __ Drop(count);
540 __ Move(result_register(), reg); 540 __ Move(result_register(), reg);
541 } 541 }
542 542
543 543
544 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, 544 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
545 Register reg) const { 545 Register reg) const {
546 ASSERT(count > 0); 546 DCHECK(count > 0);
547 if (count > 1) __ Drop(count - 1); 547 if (count > 1) __ Drop(count - 1);
548 __ mov(Operand(esp, 0), reg); 548 __ mov(Operand(esp, 0), reg);
549 } 549 }
550 550
551 551
552 void FullCodeGenerator::TestContext::DropAndPlug(int count, 552 void FullCodeGenerator::TestContext::DropAndPlug(int count,
553 Register reg) const { 553 Register reg) const {
554 ASSERT(count > 0); 554 DCHECK(count > 0);
555 // For simplicity we always test the accumulator register. 555 // For simplicity we always test the accumulator register.
556 __ Drop(count); 556 __ Drop(count);
557 __ Move(result_register(), reg); 557 __ Move(result_register(), reg);
558 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 558 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
559 codegen()->DoTest(this); 559 codegen()->DoTest(this);
560 } 560 }
561 561
562 562
563 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 563 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
564 Label* materialize_false) const { 564 Label* materialize_false) const {
565 ASSERT(materialize_true == materialize_false); 565 DCHECK(materialize_true == materialize_false);
566 __ bind(materialize_true); 566 __ bind(materialize_true);
567 } 567 }
568 568
569 569
570 void FullCodeGenerator::AccumulatorValueContext::Plug( 570 void FullCodeGenerator::AccumulatorValueContext::Plug(
571 Label* materialize_true, 571 Label* materialize_true,
572 Label* materialize_false) const { 572 Label* materialize_false) const {
573 Label done; 573 Label done;
574 __ bind(materialize_true); 574 __ bind(materialize_true);
575 __ mov(result_register(), isolate()->factory()->true_value()); 575 __ mov(result_register(), isolate()->factory()->true_value());
(...skipping 12 matching lines...) Expand all
588 __ push(Immediate(isolate()->factory()->true_value())); 588 __ push(Immediate(isolate()->factory()->true_value()));
589 __ jmp(&done, Label::kNear); 589 __ jmp(&done, Label::kNear);
590 __ bind(materialize_false); 590 __ bind(materialize_false);
591 __ push(Immediate(isolate()->factory()->false_value())); 591 __ push(Immediate(isolate()->factory()->false_value()));
592 __ bind(&done); 592 __ bind(&done);
593 } 593 }
594 594
595 595
596 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 596 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
597 Label* materialize_false) const { 597 Label* materialize_false) const {
598 ASSERT(materialize_true == true_label_); 598 DCHECK(materialize_true == true_label_);
599 ASSERT(materialize_false == false_label_); 599 DCHECK(materialize_false == false_label_);
600 } 600 }
601 601
602 602
603 void FullCodeGenerator::EffectContext::Plug(bool flag) const { 603 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
604 } 604 }
605 605
606 606
607 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 607 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
608 Handle<Object> value = flag 608 Handle<Object> value = flag
609 ? isolate()->factory()->true_value() 609 ? isolate()->factory()->true_value()
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 } else if (if_true == fall_through) { 654 } else if (if_true == fall_through) {
655 __ j(NegateCondition(cc), if_false); 655 __ j(NegateCondition(cc), if_false);
656 } else { 656 } else {
657 __ j(cc, if_true); 657 __ j(cc, if_true);
658 __ jmp(if_false); 658 __ jmp(if_false);
659 } 659 }
660 } 660 }
661 661
662 662
663 MemOperand FullCodeGenerator::StackOperand(Variable* var) { 663 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
664 ASSERT(var->IsStackAllocated()); 664 DCHECK(var->IsStackAllocated());
665 // Offset is negative because higher indexes are at lower addresses. 665 // Offset is negative because higher indexes are at lower addresses.
666 int offset = -var->index() * kPointerSize; 666 int offset = -var->index() * kPointerSize;
667 // Adjust by a (parameter or local) base offset. 667 // Adjust by a (parameter or local) base offset.
668 if (var->IsParameter()) { 668 if (var->IsParameter()) {
669 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 669 offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
670 } else { 670 } else {
671 offset += JavaScriptFrameConstants::kLocal0Offset; 671 offset += JavaScriptFrameConstants::kLocal0Offset;
672 } 672 }
673 return Operand(ebp, offset); 673 return Operand(ebp, offset);
674 } 674 }
675 675
676 676
677 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 677 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
678 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 678 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
679 if (var->IsContextSlot()) { 679 if (var->IsContextSlot()) {
680 int context_chain_length = scope()->ContextChainLength(var->scope()); 680 int context_chain_length = scope()->ContextChainLength(var->scope());
681 __ LoadContext(scratch, context_chain_length); 681 __ LoadContext(scratch, context_chain_length);
682 return ContextOperand(scratch, var->index()); 682 return ContextOperand(scratch, var->index());
683 } else { 683 } else {
684 return StackOperand(var); 684 return StackOperand(var);
685 } 685 }
686 } 686 }
687 687
688 688
689 void FullCodeGenerator::GetVar(Register dest, Variable* var) { 689 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
690 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 690 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
691 MemOperand location = VarOperand(var, dest); 691 MemOperand location = VarOperand(var, dest);
692 __ mov(dest, location); 692 __ mov(dest, location);
693 } 693 }
694 694
695 695
696 void FullCodeGenerator::SetVar(Variable* var, 696 void FullCodeGenerator::SetVar(Variable* var,
697 Register src, 697 Register src,
698 Register scratch0, 698 Register scratch0,
699 Register scratch1) { 699 Register scratch1) {
700 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 700 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
701 ASSERT(!scratch0.is(src)); 701 DCHECK(!scratch0.is(src));
702 ASSERT(!scratch0.is(scratch1)); 702 DCHECK(!scratch0.is(scratch1));
703 ASSERT(!scratch1.is(src)); 703 DCHECK(!scratch1.is(src));
704 MemOperand location = VarOperand(var, scratch0); 704 MemOperand location = VarOperand(var, scratch0);
705 __ mov(location, src); 705 __ mov(location, src);
706 706
707 // Emit the write barrier code if the location is in the heap. 707 // Emit the write barrier code if the location is in the heap.
708 if (var->IsContextSlot()) { 708 if (var->IsContextSlot()) {
709 int offset = Context::SlotOffset(var->index()); 709 int offset = Context::SlotOffset(var->index());
710 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); 710 DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
711 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 711 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
712 } 712 }
713 } 713 }
714 714
715 715
716 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 716 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
717 bool should_normalize, 717 bool should_normalize,
718 Label* if_true, 718 Label* if_true,
719 Label* if_false) { 719 Label* if_false) {
720 // Only prepare for bailouts before splits if we're in a test 720 // Only prepare for bailouts before splits if we're in a test
721 // context. Otherwise, we let the Visit function deal with the 721 // context. Otherwise, we let the Visit function deal with the
722 // preparation to avoid preparing with the same AST id twice. 722 // preparation to avoid preparing with the same AST id twice.
723 if (!context()->IsTest() || !info_->IsOptimizable()) return; 723 if (!context()->IsTest() || !info_->IsOptimizable()) return;
724 724
725 Label skip; 725 Label skip;
726 if (should_normalize) __ jmp(&skip, Label::kNear); 726 if (should_normalize) __ jmp(&skip, Label::kNear);
727 PrepareForBailout(expr, TOS_REG); 727 PrepareForBailout(expr, TOS_REG);
728 if (should_normalize) { 728 if (should_normalize) {
729 __ cmp(eax, isolate()->factory()->true_value()); 729 __ cmp(eax, isolate()->factory()->true_value());
730 Split(equal, if_true, if_false, NULL); 730 Split(equal, if_true, if_false, NULL);
731 __ bind(&skip); 731 __ bind(&skip);
732 } 732 }
733 } 733 }
734 734
735 735
736 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 736 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
737 // The variable in the declaration always resides in the current context. 737 // The variable in the declaration always resides in the current context.
738 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 738 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
739 if (generate_debug_code_) { 739 if (generate_debug_code_) {
740 // Check that we're not inside a with or catch context. 740 // Check that we're not inside a with or catch context.
741 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); 741 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
742 __ cmp(ebx, isolate()->factory()->with_context_map()); 742 __ cmp(ebx, isolate()->factory()->with_context_map());
743 __ Check(not_equal, kDeclarationInWithContext); 743 __ Check(not_equal, kDeclarationInWithContext);
744 __ cmp(ebx, isolate()->factory()->catch_context_map()); 744 __ cmp(ebx, isolate()->factory()->catch_context_map());
745 __ Check(not_equal, kDeclarationInCatchContext); 745 __ Check(not_equal, kDeclarationInCatchContext);
746 } 746 }
747 } 747 }
748 748
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 // No write barrier since the hole value is in old space. 782 // No write barrier since the hole value is in old space.
783 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 783 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
784 } 784 }
785 break; 785 break;
786 786
787 case Variable::LOOKUP: { 787 case Variable::LOOKUP: {
788 Comment cmnt(masm_, "[ VariableDeclaration"); 788 Comment cmnt(masm_, "[ VariableDeclaration");
789 __ push(esi); 789 __ push(esi);
790 __ push(Immediate(variable->name())); 790 __ push(Immediate(variable->name()));
791 // VariableDeclaration nodes are always introduced in one of four modes. 791 // VariableDeclaration nodes are always introduced in one of four modes.
792 ASSERT(IsDeclaredVariableMode(mode)); 792 DCHECK(IsDeclaredVariableMode(mode));
793 PropertyAttributes attr = 793 PropertyAttributes attr =
794 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; 794 IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
795 __ push(Immediate(Smi::FromInt(attr))); 795 __ push(Immediate(Smi::FromInt(attr)));
796 // Push initial value, if any. 796 // Push initial value, if any.
797 // Note: For variables we must not push an initial value (such as 797 // Note: For variables we must not push an initial value (such as
798 // 'undefined') because we may have a (legal) redeclaration and we 798 // 'undefined') because we may have a (legal) redeclaration and we
799 // must not destroy the current value. 799 // must not destroy the current value.
800 if (hole_init) { 800 if (hole_init) {
801 __ push(Immediate(isolate()->factory()->the_hole_value())); 801 __ push(Immediate(isolate()->factory()->the_hole_value()));
802 } else { 802 } else {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 VisitForStackValue(declaration->fun()); 857 VisitForStackValue(declaration->fun());
858 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 858 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
859 break; 859 break;
860 } 860 }
861 } 861 }
862 } 862 }
863 863
864 864
865 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 865 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
866 Variable* variable = declaration->proxy()->var(); 866 Variable* variable = declaration->proxy()->var();
867 ASSERT(variable->location() == Variable::CONTEXT); 867 DCHECK(variable->location() == Variable::CONTEXT);
868 ASSERT(variable->interface()->IsFrozen()); 868 DCHECK(variable->interface()->IsFrozen());
869 869
870 Comment cmnt(masm_, "[ ModuleDeclaration"); 870 Comment cmnt(masm_, "[ ModuleDeclaration");
871 EmitDebugCheckDeclarationContext(variable); 871 EmitDebugCheckDeclarationContext(variable);
872 872
873 // Load instance object. 873 // Load instance object.
874 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope())); 874 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope()));
875 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); 875 __ mov(eax, ContextOperand(eax, variable->interface()->Index()));
876 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); 876 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX));
877 877
878 // Assign it. 878 // Assign it.
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 1148
1149 // Check if the expected map still matches that of the enumerable. 1149 // Check if the expected map still matches that of the enumerable.
1150 // If not, we may have to filter the key. 1150 // If not, we may have to filter the key.
1151 Label update_each; 1151 Label update_each;
1152 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1152 __ mov(ecx, Operand(esp, 4 * kPointerSize));
1153 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 1153 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1154 __ j(equal, &update_each, Label::kNear); 1154 __ j(equal, &update_each, Label::kNear);
1155 1155
1156 // For proxies, no filtering is done. 1156 // For proxies, no filtering is done.
1157 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1157 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1158 ASSERT(Smi::FromInt(0) == 0); 1158 DCHECK(Smi::FromInt(0) == 0);
1159 __ test(edx, edx); 1159 __ test(edx, edx);
1160 __ j(zero, &update_each); 1160 __ j(zero, &update_each);
1161 1161
1162 // Convert the entry to a string or null if it isn't a property 1162 // Convert the entry to a string or null if it isn't a property
1163 // anymore. If the property has been removed while iterating, we 1163 // anymore. If the property has been removed while iterating, we
1164 // just skip it. 1164 // just skip it.
1165 __ push(ecx); // Enumerable. 1165 __ push(ecx); // Enumerable.
1166 __ push(ebx); // Current entry. 1166 __ push(ebx); // Current entry.
1167 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1167 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1168 __ test(eax, eax); 1168 __ test(eax, eax);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1338 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) 1338 ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1339 ? NOT_CONTEXTUAL 1339 ? NOT_CONTEXTUAL
1340 : CONTEXTUAL; 1340 : CONTEXTUAL;
1341 1341
1342 CallLoadIC(mode); 1342 CallLoadIC(mode);
1343 } 1343 }
1344 1344
1345 1345
1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1347 Label* slow) { 1347 Label* slow) {
1348 ASSERT(var->IsContextSlot()); 1348 DCHECK(var->IsContextSlot());
1349 Register context = esi; 1349 Register context = esi;
1350 Register temp = ebx; 1350 Register temp = ebx;
1351 1351
1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1353 if (s->num_heap_slots() > 0) { 1353 if (s->num_heap_slots() > 0) {
1354 if (s->calls_sloppy_eval()) { 1354 if (s->calls_sloppy_eval()) {
1355 // Check that extension is NULL. 1355 // Check that extension is NULL.
1356 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), 1356 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
1357 Immediate(0)); 1357 Immediate(0));
1358 __ j(not_equal, slow); 1358 __ j(not_equal, slow);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 case Variable::LOCAL: 1430 case Variable::LOCAL:
1431 case Variable::CONTEXT: { 1431 case Variable::CONTEXT: {
1432 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1432 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1433 : "[ Stack variable"); 1433 : "[ Stack variable");
1434 if (var->binding_needs_init()) { 1434 if (var->binding_needs_init()) {
1435 // var->scope() may be NULL when the proxy is located in eval code and 1435 // var->scope() may be NULL when the proxy is located in eval code and
1436 // refers to a potential outside binding. Currently those bindings are 1436 // refers to a potential outside binding. Currently those bindings are
1437 // always looked up dynamically, i.e. in that case 1437 // always looked up dynamically, i.e. in that case
1438 // var->location() == LOOKUP. 1438 // var->location() == LOOKUP.
1439 // always holds. 1439 // always holds.
1440 ASSERT(var->scope() != NULL); 1440 DCHECK(var->scope() != NULL);
1441 1441
1442 // Check if the binding really needs an initialization check. The check 1442 // Check if the binding really needs an initialization check. The check
1443 // can be skipped in the following situation: we have a LET or CONST 1443 // can be skipped in the following situation: we have a LET or CONST
1444 // binding in harmony mode, both the Variable and the VariableProxy have 1444 // binding in harmony mode, both the Variable and the VariableProxy have
1445 // the same declaration scope (i.e. they are both in global code, in the 1445 // the same declaration scope (i.e. they are both in global code, in the
1446 // same function or in the same eval code) and the VariableProxy is in 1446 // same function or in the same eval code) and the VariableProxy is in
1447 // the source physically located after the initializer of the variable. 1447 // the source physically located after the initializer of the variable.
1448 // 1448 //
1449 // We cannot skip any initialization checks for CONST in non-harmony 1449 // We cannot skip any initialization checks for CONST in non-harmony
1450 // mode because const variables may be declared but never initialized: 1450 // mode because const variables may be declared but never initialized:
1451 // if (false) { const x; }; var y = x; 1451 // if (false) { const x; }; var y = x;
1452 // 1452 //
1453 // The condition on the declaration scopes is a conservative check for 1453 // The condition on the declaration scopes is a conservative check for
1454 // nested functions that access a binding and are called before the 1454 // nested functions that access a binding and are called before the
1455 // binding is initialized: 1455 // binding is initialized:
1456 // function() { f(); let x = 1; function f() { x = 2; } } 1456 // function() { f(); let x = 1; function f() { x = 2; } }
1457 // 1457 //
1458 bool skip_init_check; 1458 bool skip_init_check;
1459 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 1459 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1460 skip_init_check = false; 1460 skip_init_check = false;
1461 } else { 1461 } else {
1462 // Check that we always have valid source position. 1462 // Check that we always have valid source position.
1463 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); 1463 DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
1464 ASSERT(proxy->position() != RelocInfo::kNoPosition); 1464 DCHECK(proxy->position() != RelocInfo::kNoPosition);
1465 skip_init_check = var->mode() != CONST_LEGACY && 1465 skip_init_check = var->mode() != CONST_LEGACY &&
1466 var->initializer_position() < proxy->position(); 1466 var->initializer_position() < proxy->position();
1467 } 1467 }
1468 1468
1469 if (!skip_init_check) { 1469 if (!skip_init_check) {
1470 // Let and const need a read barrier. 1470 // Let and const need a read barrier.
1471 Label done; 1471 Label done;
1472 GetVar(eax, var); 1472 GetVar(eax, var);
1473 __ cmp(eax, isolate()->factory()->the_hole_value()); 1473 __ cmp(eax, isolate()->factory()->the_hole_value());
1474 __ j(not_equal, &done, Label::kNear); 1474 __ j(not_equal, &done, Label::kNear);
1475 if (var->mode() == LET || var->mode() == CONST) { 1475 if (var->mode() == LET || var->mode() == CONST) {
1476 // Throw a reference error when using an uninitialized let/const 1476 // Throw a reference error when using an uninitialized let/const
1477 // binding in harmony mode. 1477 // binding in harmony mode.
1478 __ push(Immediate(var->name())); 1478 __ push(Immediate(var->name()));
1479 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1479 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1480 } else { 1480 } else {
1481 // Uninitalized const bindings outside of harmony mode are unholed. 1481 // Uninitalized const bindings outside of harmony mode are unholed.
1482 ASSERT(var->mode() == CONST_LEGACY); 1482 DCHECK(var->mode() == CONST_LEGACY);
1483 __ mov(eax, isolate()->factory()->undefined_value()); 1483 __ mov(eax, isolate()->factory()->undefined_value());
1484 } 1484 }
1485 __ bind(&done); 1485 __ bind(&done);
1486 context()->Plug(eax); 1486 context()->Plug(eax);
1487 break; 1487 break;
1488 } 1488 }
1489 } 1489 }
1490 context()->Plug(var); 1490 context()->Plug(var);
1491 break; 1491 break;
1492 } 1492 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 Literal* key = property->key(); 1621 Literal* key = property->key();
1622 Expression* value = property->value(); 1622 Expression* value = property->value();
1623 if (!result_saved) { 1623 if (!result_saved) {
1624 __ push(eax); // Save result on the stack 1624 __ push(eax); // Save result on the stack
1625 result_saved = true; 1625 result_saved = true;
1626 } 1626 }
1627 switch (property->kind()) { 1627 switch (property->kind()) {
1628 case ObjectLiteral::Property::CONSTANT: 1628 case ObjectLiteral::Property::CONSTANT:
1629 UNREACHABLE(); 1629 UNREACHABLE();
1630 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1630 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1631 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1631 DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1632 // Fall through. 1632 // Fall through.
1633 case ObjectLiteral::Property::COMPUTED: 1633 case ObjectLiteral::Property::COMPUTED:
1634 if (key->value()->IsInternalizedString()) { 1634 if (key->value()->IsInternalizedString()) {
1635 if (property->emit_store()) { 1635 if (property->emit_store()) {
1636 VisitForAccumulatorValue(value); 1636 VisitForAccumulatorValue(value);
1637 ASSERT(StoreIC::ValueRegister().is(eax)); 1637 DCHECK(StoreIC::ValueRegister().is(eax));
1638 __ mov(StoreIC::NameRegister(), Immediate(key->value())); 1638 __ mov(StoreIC::NameRegister(), Immediate(key->value()));
1639 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0)); 1639 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0));
1640 CallStoreIC(key->LiteralFeedbackId()); 1640 CallStoreIC(key->LiteralFeedbackId());
1641 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1641 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1642 } else { 1642 } else {
1643 VisitForEffect(value); 1643 VisitForEffect(value);
1644 } 1644 }
1645 break; 1645 break;
1646 } 1646 }
1647 __ push(Operand(esp, 0)); // Duplicate receiver. 1647 __ push(Operand(esp, 0)); // Duplicate receiver.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 ++it) { 1679 ++it) {
1680 __ push(Operand(esp, 0)); // Duplicate receiver. 1680 __ push(Operand(esp, 0)); // Duplicate receiver.
1681 VisitForStackValue(it->first); 1681 VisitForStackValue(it->first);
1682 EmitAccessor(it->second->getter); 1682 EmitAccessor(it->second->getter);
1683 EmitAccessor(it->second->setter); 1683 EmitAccessor(it->second->setter);
1684 __ push(Immediate(Smi::FromInt(NONE))); 1684 __ push(Immediate(Smi::FromInt(NONE)));
1685 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); 1685 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1686 } 1686 }
1687 1687
1688 if (expr->has_function()) { 1688 if (expr->has_function()) {
1689 ASSERT(result_saved); 1689 DCHECK(result_saved);
1690 __ push(Operand(esp, 0)); 1690 __ push(Operand(esp, 0));
1691 __ CallRuntime(Runtime::kToFastProperties, 1); 1691 __ CallRuntime(Runtime::kToFastProperties, 1);
1692 } 1692 }
1693 1693
1694 if (result_saved) { 1694 if (result_saved) {
1695 context()->PlugTOS(); 1695 context()->PlugTOS();
1696 } else { 1696 } else {
1697 context()->Plug(eax); 1697 context()->Plug(eax);
1698 } 1698 }
1699 } 1699 }
1700 1700
1701 1701
1702 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1702 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1703 Comment cmnt(masm_, "[ ArrayLiteral"); 1703 Comment cmnt(masm_, "[ ArrayLiteral");
1704 1704
1705 expr->BuildConstantElements(isolate()); 1705 expr->BuildConstantElements(isolate());
1706 int flags = expr->depth() == 1 1706 int flags = expr->depth() == 1
1707 ? ArrayLiteral::kShallowElements 1707 ? ArrayLiteral::kShallowElements
1708 : ArrayLiteral::kNoFlags; 1708 : ArrayLiteral::kNoFlags;
1709 1709
1710 ZoneList<Expression*>* subexprs = expr->values(); 1710 ZoneList<Expression*>* subexprs = expr->values();
1711 int length = subexprs->length(); 1711 int length = subexprs->length();
1712 Handle<FixedArray> constant_elements = expr->constant_elements(); 1712 Handle<FixedArray> constant_elements = expr->constant_elements();
1713 ASSERT_EQ(2, constant_elements->length()); 1713 DCHECK_EQ(2, constant_elements->length());
1714 ElementsKind constant_elements_kind = 1714 ElementsKind constant_elements_kind =
1715 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1715 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1716 bool has_constant_fast_elements = 1716 bool has_constant_fast_elements =
1717 IsFastObjectElementsKind(constant_elements_kind); 1717 IsFastObjectElementsKind(constant_elements_kind);
1718 Handle<FixedArrayBase> constant_elements_values( 1718 Handle<FixedArrayBase> constant_elements_values(
1719 FixedArrayBase::cast(constant_elements->get(1))); 1719 FixedArrayBase::cast(constant_elements->get(1)));
1720 1720
1721 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1721 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1722 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { 1722 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1723 // If the only customer of allocation sites is transitioning, then 1723 // If the only customer of allocation sites is transitioning, then
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 if (result_saved) { 1784 if (result_saved) {
1785 __ add(esp, Immediate(kPointerSize)); // literal index 1785 __ add(esp, Immediate(kPointerSize)); // literal index
1786 context()->PlugTOS(); 1786 context()->PlugTOS();
1787 } else { 1787 } else {
1788 context()->Plug(eax); 1788 context()->Plug(eax);
1789 } 1789 }
1790 } 1790 }
1791 1791
1792 1792
1793 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1793 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1794 ASSERT(expr->target()->IsValidReferenceExpression()); 1794 DCHECK(expr->target()->IsValidReferenceExpression());
1795 1795
1796 Comment cmnt(masm_, "[ Assignment"); 1796 Comment cmnt(masm_, "[ Assignment");
1797 1797
1798 // Left-hand side can only be a property, a global or a (parameter or local) 1798 // Left-hand side can only be a property, a global or a (parameter or local)
1799 // slot. 1799 // slot.
1800 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1800 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1801 LhsKind assign_type = VARIABLE; 1801 LhsKind assign_type = VARIABLE;
1802 Property* property = expr->target()->AsProperty(); 1802 Property* property = expr->target()->AsProperty();
1803 if (property != NULL) { 1803 if (property != NULL) {
1804 assign_type = (property->key()->IsPropertyName()) 1804 assign_type = (property->key()->IsPropertyName())
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1915 case Yield::INITIAL: { 1915 case Yield::INITIAL: {
1916 Label suspend, continuation, post_runtime, resume; 1916 Label suspend, continuation, post_runtime, resume;
1917 1917
1918 __ jmp(&suspend); 1918 __ jmp(&suspend);
1919 1919
1920 __ bind(&continuation); 1920 __ bind(&continuation);
1921 __ jmp(&resume); 1921 __ jmp(&resume);
1922 1922
1923 __ bind(&suspend); 1923 __ bind(&suspend);
1924 VisitForAccumulatorValue(expr->generator_object()); 1924 VisitForAccumulatorValue(expr->generator_object());
1925 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 1925 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1926 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), 1926 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
1927 Immediate(Smi::FromInt(continuation.pos()))); 1927 Immediate(Smi::FromInt(continuation.pos())));
1928 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); 1928 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
1929 __ mov(ecx, esi); 1929 __ mov(ecx, esi);
1930 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, 1930 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
1931 kDontSaveFPRegs); 1931 kDontSaveFPRegs);
1932 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); 1932 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
1933 __ cmp(esp, ebx); 1933 __ cmp(esp, ebx);
1934 __ j(equal, &post_runtime); 1934 __ j(equal, &post_runtime);
1935 __ push(eax); // generator object 1935 __ push(eax); // generator object
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1990 __ PushTryHandler(StackHandler::CATCH, expr->index()); 1990 __ PushTryHandler(StackHandler::CATCH, expr->index());
1991 const int handler_size = StackHandlerConstants::kSize; 1991 const int handler_size = StackHandlerConstants::kSize;
1992 __ push(eax); // result 1992 __ push(eax); // result
1993 __ jmp(&l_suspend); 1993 __ jmp(&l_suspend);
1994 __ bind(&l_continuation); 1994 __ bind(&l_continuation);
1995 __ jmp(&l_resume); 1995 __ jmp(&l_resume);
1996 __ bind(&l_suspend); 1996 __ bind(&l_suspend);
1997 const int generator_object_depth = kPointerSize + handler_size; 1997 const int generator_object_depth = kPointerSize + handler_size;
1998 __ mov(eax, Operand(esp, generator_object_depth)); 1998 __ mov(eax, Operand(esp, generator_object_depth));
1999 __ push(eax); // g 1999 __ push(eax); // g
2000 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2000 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2001 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), 2001 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
2002 Immediate(Smi::FromInt(l_continuation.pos()))); 2002 Immediate(Smi::FromInt(l_continuation.pos())));
2003 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); 2003 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
2004 __ mov(ecx, esi); 2004 __ mov(ecx, esi);
2005 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, 2005 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
2006 kDontSaveFPRegs); 2006 kDontSaveFPRegs);
2007 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2007 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2008 __ mov(context_register(), 2008 __ mov(context_register(),
2009 Operand(ebp, StandardFrameConstants::kContextOffset)); 2009 Operand(ebp, StandardFrameConstants::kContextOffset));
2010 __ pop(eax); // result 2010 __ pop(eax); // result
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2193 __ bind(&gc_required); 2193 __ bind(&gc_required);
2194 __ Push(Smi::FromInt(map->instance_size())); 2194 __ Push(Smi::FromInt(map->instance_size()));
2195 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 2195 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2196 __ mov(context_register(), 2196 __ mov(context_register(),
2197 Operand(ebp, StandardFrameConstants::kContextOffset)); 2197 Operand(ebp, StandardFrameConstants::kContextOffset));
2198 2198
2199 __ bind(&allocated); 2199 __ bind(&allocated);
2200 __ mov(ebx, map); 2200 __ mov(ebx, map);
2201 __ pop(ecx); 2201 __ pop(ecx);
2202 __ mov(edx, isolate()->factory()->ToBoolean(done)); 2202 __ mov(edx, isolate()->factory()->ToBoolean(done));
2203 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2203 DCHECK_EQ(map->instance_size(), 5 * kPointerSize);
2204 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); 2204 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
2205 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), 2205 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
2206 isolate()->factory()->empty_fixed_array()); 2206 isolate()->factory()->empty_fixed_array());
2207 __ mov(FieldOperand(eax, JSObject::kElementsOffset), 2207 __ mov(FieldOperand(eax, JSObject::kElementsOffset),
2208 isolate()->factory()->empty_fixed_array()); 2208 isolate()->factory()->empty_fixed_array());
2209 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); 2209 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx);
2210 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); 2210 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx);
2211 2211
2212 // Only the value field needs a write barrier, as the other values are in the 2212 // Only the value field needs a write barrier, as the other values are in the
2213 // root set. 2213 // root set.
2214 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, 2214 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
2215 ecx, edx, kDontSaveFPRegs); 2215 ecx, edx, kDontSaveFPRegs);
2216 } 2216 }
2217 2217
2218 2218
2219 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2219 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2220 SetSourcePosition(prop->position()); 2220 SetSourcePosition(prop->position());
2221 Literal* key = prop->key()->AsLiteral(); 2221 Literal* key = prop->key()->AsLiteral();
2222 ASSERT(!key->value()->IsSmi()); 2222 DCHECK(!key->value()->IsSmi());
2223 __ mov(LoadIC::NameRegister(), Immediate(key->value())); 2223 __ mov(LoadIC::NameRegister(), Immediate(key->value()));
2224 if (FLAG_vector_ics) { 2224 if (FLAG_vector_ics) {
2225 __ mov(LoadIC::SlotRegister(), 2225 __ mov(LoadIC::SlotRegister(),
2226 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); 2226 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
2227 CallLoadIC(NOT_CONTEXTUAL); 2227 CallLoadIC(NOT_CONTEXTUAL);
2228 } else { 2228 } else {
2229 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2229 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2230 } 2230 }
2231 } 2231 }
2232 2232
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 __ pop(edx); 2345 __ pop(edx);
2346 BinaryOpICStub stub(isolate(), op, mode); 2346 BinaryOpICStub stub(isolate(), op, mode);
2347 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2347 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2348 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); 2348 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2349 patch_site.EmitPatchInfo(); 2349 patch_site.EmitPatchInfo();
2350 context()->Plug(eax); 2350 context()->Plug(eax);
2351 } 2351 }
2352 2352
2353 2353
2354 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2354 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2355 ASSERT(expr->IsValidReferenceExpression()); 2355 DCHECK(expr->IsValidReferenceExpression());
2356 2356
2357 // Left-hand side can only be a property, a global or a (parameter or local) 2357 // Left-hand side can only be a property, a global or a (parameter or local)
2358 // slot. 2358 // slot.
2359 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2359 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2360 LhsKind assign_type = VARIABLE; 2360 LhsKind assign_type = VARIABLE;
2361 Property* prop = expr->AsProperty(); 2361 Property* prop = expr->AsProperty();
2362 if (prop != NULL) { 2362 if (prop != NULL) {
2363 assign_type = (prop->key()->IsPropertyName()) 2363 assign_type = (prop->key()->IsPropertyName())
2364 ? NAMED_PROPERTY 2364 ? NAMED_PROPERTY
2365 : KEYED_PROPERTY; 2365 : KEYED_PROPERTY;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2413 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2413 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2414 Token::Value op) { 2414 Token::Value op) {
2415 if (var->IsUnallocated()) { 2415 if (var->IsUnallocated()) {
2416 // Global var, const, or let. 2416 // Global var, const, or let.
2417 __ mov(StoreIC::NameRegister(), var->name()); 2417 __ mov(StoreIC::NameRegister(), var->name());
2418 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand()); 2418 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand());
2419 CallStoreIC(); 2419 CallStoreIC();
2420 2420
2421 } else if (op == Token::INIT_CONST_LEGACY) { 2421 } else if (op == Token::INIT_CONST_LEGACY) {
2422 // Const initializers need a write barrier. 2422 // Const initializers need a write barrier.
2423 ASSERT(!var->IsParameter()); // No const parameters. 2423 DCHECK(!var->IsParameter()); // No const parameters.
2424 if (var->IsLookupSlot()) { 2424 if (var->IsLookupSlot()) {
2425 __ push(eax); 2425 __ push(eax);
2426 __ push(esi); 2426 __ push(esi);
2427 __ push(Immediate(var->name())); 2427 __ push(Immediate(var->name()));
2428 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); 2428 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2429 } else { 2429 } else {
2430 ASSERT(var->IsStackLocal() || var->IsContextSlot()); 2430 DCHECK(var->IsStackLocal() || var->IsContextSlot());
2431 Label skip; 2431 Label skip;
2432 MemOperand location = VarOperand(var, ecx); 2432 MemOperand location = VarOperand(var, ecx);
2433 __ mov(edx, location); 2433 __ mov(edx, location);
2434 __ cmp(edx, isolate()->factory()->the_hole_value()); 2434 __ cmp(edx, isolate()->factory()->the_hole_value());
2435 __ j(not_equal, &skip, Label::kNear); 2435 __ j(not_equal, &skip, Label::kNear);
2436 EmitStoreToStackLocalOrContextSlot(var, location); 2436 EmitStoreToStackLocalOrContextSlot(var, location);
2437 __ bind(&skip); 2437 __ bind(&skip);
2438 } 2438 }
2439 2439
2440 } else if (var->mode() == LET && op != Token::INIT_LET) { 2440 } else if (var->mode() == LET && op != Token::INIT_LET) {
2441 // Non-initializing assignment to let variable needs a write barrier. 2441 // Non-initializing assignment to let variable needs a write barrier.
2442 ASSERT(!var->IsLookupSlot()); 2442 DCHECK(!var->IsLookupSlot());
2443 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2443 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2444 Label assign; 2444 Label assign;
2445 MemOperand location = VarOperand(var, ecx); 2445 MemOperand location = VarOperand(var, ecx);
2446 __ mov(edx, location); 2446 __ mov(edx, location);
2447 __ cmp(edx, isolate()->factory()->the_hole_value()); 2447 __ cmp(edx, isolate()->factory()->the_hole_value());
2448 __ j(not_equal, &assign, Label::kNear); 2448 __ j(not_equal, &assign, Label::kNear);
2449 __ push(Immediate(var->name())); 2449 __ push(Immediate(var->name()));
2450 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2450 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2451 __ bind(&assign); 2451 __ bind(&assign);
2452 EmitStoreToStackLocalOrContextSlot(var, location); 2452 EmitStoreToStackLocalOrContextSlot(var, location);
2453 2453
2454 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2454 } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2455 if (var->IsLookupSlot()) { 2455 if (var->IsLookupSlot()) {
2456 // Assignment to var. 2456 // Assignment to var.
2457 __ push(eax); // Value. 2457 __ push(eax); // Value.
2458 __ push(esi); // Context. 2458 __ push(esi); // Context.
2459 __ push(Immediate(var->name())); 2459 __ push(Immediate(var->name()));
2460 __ push(Immediate(Smi::FromInt(strict_mode()))); 2460 __ push(Immediate(Smi::FromInt(strict_mode())));
2461 __ CallRuntime(Runtime::kStoreLookupSlot, 4); 2461 __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2462 } else { 2462 } else {
2463 // Assignment to var or initializing assignment to let/const in harmony 2463 // Assignment to var or initializing assignment to let/const in harmony
2464 // mode. 2464 // mode.
2465 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2465 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2466 MemOperand location = VarOperand(var, ecx); 2466 MemOperand location = VarOperand(var, ecx);
2467 if (generate_debug_code_ && op == Token::INIT_LET) { 2467 if (generate_debug_code_ && op == Token::INIT_LET) {
2468 // Check for an uninitialized let binding. 2468 // Check for an uninitialized let binding.
2469 __ mov(edx, location); 2469 __ mov(edx, location);
2470 __ cmp(edx, isolate()->factory()->the_hole_value()); 2470 __ cmp(edx, isolate()->factory()->the_hole_value());
2471 __ Check(equal, kLetBindingReInitialization); 2471 __ Check(equal, kLetBindingReInitialization);
2472 } 2472 }
2473 EmitStoreToStackLocalOrContextSlot(var, location); 2473 EmitStoreToStackLocalOrContextSlot(var, location);
2474 } 2474 }
2475 } 2475 }
2476 // Non-initializing assignments to consts are ignored. 2476 // Non-initializing assignments to consts are ignored.
2477 } 2477 }
2478 2478
2479 2479
2480 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2480 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2481 // Assignment to a property, using a named store IC. 2481 // Assignment to a property, using a named store IC.
2482 // eax : value 2482 // eax : value
2483 // esp[0] : receiver 2483 // esp[0] : receiver
2484 2484
2485 Property* prop = expr->target()->AsProperty(); 2485 Property* prop = expr->target()->AsProperty();
2486 ASSERT(prop != NULL); 2486 DCHECK(prop != NULL);
2487 ASSERT(prop->key()->IsLiteral()); 2487 DCHECK(prop->key()->IsLiteral());
2488 2488
2489 // Record source code position before IC call. 2489 // Record source code position before IC call.
2490 SetSourcePosition(expr->position()); 2490 SetSourcePosition(expr->position());
2491 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); 2491 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
2492 __ pop(StoreIC::ReceiverRegister()); 2492 __ pop(StoreIC::ReceiverRegister());
2493 CallStoreIC(expr->AssignmentFeedbackId()); 2493 CallStoreIC(expr->AssignmentFeedbackId());
2494 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2494 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2495 context()->Plug(eax); 2495 context()->Plug(eax);
2496 } 2496 }
2497 2497
2498 2498
2499 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2499 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2500 // Assignment to a property, using a keyed store IC. 2500 // Assignment to a property, using a keyed store IC.
2501 // eax : value 2501 // eax : value
2502 // esp[0] : key 2502 // esp[0] : key
2503 // esp[kPointerSize] : receiver 2503 // esp[kPointerSize] : receiver
2504 2504
2505 __ pop(KeyedStoreIC::NameRegister()); // Key. 2505 __ pop(KeyedStoreIC::NameRegister()); // Key.
2506 __ pop(KeyedStoreIC::ReceiverRegister()); 2506 __ pop(KeyedStoreIC::ReceiverRegister());
2507 ASSERT(KeyedStoreIC::ValueRegister().is(eax)); 2507 DCHECK(KeyedStoreIC::ValueRegister().is(eax));
2508 // Record source code position before IC call. 2508 // Record source code position before IC call.
2509 SetSourcePosition(expr->position()); 2509 SetSourcePosition(expr->position());
2510 Handle<Code> ic = strict_mode() == SLOPPY 2510 Handle<Code> ic = strict_mode() == SLOPPY
2511 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2511 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2512 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2512 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2513 CallIC(ic, expr->AssignmentFeedbackId()); 2513 CallIC(ic, expr->AssignmentFeedbackId());
2514 2514
2515 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2515 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2516 context()->Plug(eax); 2516 context()->Plug(eax);
2517 } 2517 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2556 if (call_type == CallIC::FUNCTION) { 2556 if (call_type == CallIC::FUNCTION) {
2557 { StackValueContext context(this); 2557 { StackValueContext context(this);
2558 EmitVariableLoad(callee->AsVariableProxy()); 2558 EmitVariableLoad(callee->AsVariableProxy());
2559 PrepareForBailout(callee, NO_REGISTERS); 2559 PrepareForBailout(callee, NO_REGISTERS);
2560 } 2560 }
2561 // Push undefined as receiver. This is patched in the method prologue if it 2561 // Push undefined as receiver. This is patched in the method prologue if it
2562 // is a sloppy mode method. 2562 // is a sloppy mode method.
2563 __ push(Immediate(isolate()->factory()->undefined_value())); 2563 __ push(Immediate(isolate()->factory()->undefined_value()));
2564 } else { 2564 } else {
2565 // Load the function from the receiver. 2565 // Load the function from the receiver.
2566 ASSERT(callee->IsProperty()); 2566 DCHECK(callee->IsProperty());
2567 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); 2567 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
2568 EmitNamedPropertyLoad(callee->AsProperty()); 2568 EmitNamedPropertyLoad(callee->AsProperty());
2569 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2569 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2570 // Push the target function under the receiver. 2570 // Push the target function under the receiver.
2571 __ push(Operand(esp, 0)); 2571 __ push(Operand(esp, 0));
2572 __ mov(Operand(esp, kPointerSize), eax); 2572 __ mov(Operand(esp, kPointerSize), eax);
2573 } 2573 }
2574 2574
2575 EmitCall(expr, call_type); 2575 EmitCall(expr, call_type);
2576 } 2576 }
2577 2577
2578 2578
2579 // Code common for calls using the IC. 2579 // Code common for calls using the IC.
2580 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2580 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2581 Expression* key) { 2581 Expression* key) {
2582 // Load the key. 2582 // Load the key.
2583 VisitForAccumulatorValue(key); 2583 VisitForAccumulatorValue(key);
2584 2584
2585 Expression* callee = expr->expression(); 2585 Expression* callee = expr->expression();
2586 2586
2587 // Load the function from the receiver. 2587 // Load the function from the receiver.
2588 ASSERT(callee->IsProperty()); 2588 DCHECK(callee->IsProperty());
2589 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); 2589 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
2590 __ mov(LoadIC::NameRegister(), eax); 2590 __ mov(LoadIC::NameRegister(), eax);
2591 EmitKeyedPropertyLoad(callee->AsProperty()); 2591 EmitKeyedPropertyLoad(callee->AsProperty());
2592 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2592 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2593 2593
2594 // Push the target function under the receiver. 2594 // Push the target function under the receiver.
2595 __ push(Operand(esp, 0)); 2595 __ push(Operand(esp, 0));
2596 __ mov(Operand(esp, kPointerSize), eax); 2596 __ mov(Operand(esp, kPointerSize), eax);
2597 2597
2598 EmitCall(expr, CallIC::METHOD); 2598 EmitCall(expr, CallIC::METHOD);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2739 { PreservePositionScope scope(masm()->positions_recorder()); 2739 { PreservePositionScope scope(masm()->positions_recorder());
2740 VisitForStackValue(property->obj()); 2740 VisitForStackValue(property->obj());
2741 } 2741 }
2742 if (property->key()->IsPropertyName()) { 2742 if (property->key()->IsPropertyName()) {
2743 EmitCallWithLoadIC(expr); 2743 EmitCallWithLoadIC(expr);
2744 } else { 2744 } else {
2745 EmitKeyedCallWithLoadIC(expr, property->key()); 2745 EmitKeyedCallWithLoadIC(expr, property->key());
2746 } 2746 }
2747 2747
2748 } else { 2748 } else {
2749 ASSERT(call_type == Call::OTHER_CALL); 2749 DCHECK(call_type == Call::OTHER_CALL);
2750 // Call to an arbitrary expression not handled specially above. 2750 // Call to an arbitrary expression not handled specially above.
2751 { PreservePositionScope scope(masm()->positions_recorder()); 2751 { PreservePositionScope scope(masm()->positions_recorder());
2752 VisitForStackValue(callee); 2752 VisitForStackValue(callee);
2753 } 2753 }
2754 __ push(Immediate(isolate()->factory()->undefined_value())); 2754 __ push(Immediate(isolate()->factory()->undefined_value()));
2755 // Emit function call. 2755 // Emit function call.
2756 EmitCall(expr); 2756 EmitCall(expr);
2757 } 2757 }
2758 2758
2759 #ifdef DEBUG 2759 #ifdef DEBUG
2760 // RecordJSReturnSite should have been called. 2760 // RecordJSReturnSite should have been called.
2761 ASSERT(expr->return_is_recorded_); 2761 DCHECK(expr->return_is_recorded_);
2762 #endif 2762 #endif
2763 } 2763 }
2764 2764
2765 2765
2766 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2766 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2767 Comment cmnt(masm_, "[ CallNew"); 2767 Comment cmnt(masm_, "[ CallNew");
2768 // According to ECMA-262, section 11.2.2, page 44, the function 2768 // According to ECMA-262, section 11.2.2, page 44, the function
2769 // expression in new calls must be evaluated before the 2769 // expression in new calls must be evaluated before the
2770 // arguments. 2770 // arguments.
2771 2771
(...skipping 13 matching lines...) Expand all
2785 // constructor invocation. 2785 // constructor invocation.
2786 SetSourcePosition(expr->position()); 2786 SetSourcePosition(expr->position());
2787 2787
2788 // Load function and argument count into edi and eax. 2788 // Load function and argument count into edi and eax.
2789 __ Move(eax, Immediate(arg_count)); 2789 __ Move(eax, Immediate(arg_count));
2790 __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2790 __ mov(edi, Operand(esp, arg_count * kPointerSize));
2791 2791
2792 // Record call targets in unoptimized code. 2792 // Record call targets in unoptimized code.
2793 if (FLAG_pretenuring_call_new) { 2793 if (FLAG_pretenuring_call_new) {
2794 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2794 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2795 ASSERT(expr->AllocationSiteFeedbackSlot() == 2795 DCHECK(expr->AllocationSiteFeedbackSlot() ==
2796 expr->CallNewFeedbackSlot() + 1); 2796 expr->CallNewFeedbackSlot() + 1);
2797 } 2797 }
2798 2798
2799 __ LoadHeapObject(ebx, FeedbackVector()); 2799 __ LoadHeapObject(ebx, FeedbackVector());
2800 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2800 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
2801 2801
2802 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); 2802 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
2803 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 2803 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2804 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2804 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2805 context()->Plug(eax); 2805 context()->Plug(eax);
2806 } 2806 }
2807 2807
2808 2808
2809 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2809 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2810 ZoneList<Expression*>* args = expr->arguments(); 2810 ZoneList<Expression*>* args = expr->arguments();
2811 ASSERT(args->length() == 1); 2811 DCHECK(args->length() == 1);
2812 2812
2813 VisitForAccumulatorValue(args->at(0)); 2813 VisitForAccumulatorValue(args->at(0));
2814 2814
2815 Label materialize_true, materialize_false; 2815 Label materialize_true, materialize_false;
2816 Label* if_true = NULL; 2816 Label* if_true = NULL;
2817 Label* if_false = NULL; 2817 Label* if_false = NULL;
2818 Label* fall_through = NULL; 2818 Label* fall_through = NULL;
2819 context()->PrepareTest(&materialize_true, &materialize_false, 2819 context()->PrepareTest(&materialize_true, &materialize_false,
2820 &if_true, &if_false, &fall_through); 2820 &if_true, &if_false, &fall_through);
2821 2821
2822 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2822 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2823 __ test(eax, Immediate(kSmiTagMask)); 2823 __ test(eax, Immediate(kSmiTagMask));
2824 Split(zero, if_true, if_false, fall_through); 2824 Split(zero, if_true, if_false, fall_through);
2825 2825
2826 context()->Plug(if_true, if_false); 2826 context()->Plug(if_true, if_false);
2827 } 2827 }
2828 2828
2829 2829
2830 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 2830 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2831 ZoneList<Expression*>* args = expr->arguments(); 2831 ZoneList<Expression*>* args = expr->arguments();
2832 ASSERT(args->length() == 1); 2832 DCHECK(args->length() == 1);
2833 2833
2834 VisitForAccumulatorValue(args->at(0)); 2834 VisitForAccumulatorValue(args->at(0));
2835 2835
2836 Label materialize_true, materialize_false; 2836 Label materialize_true, materialize_false;
2837 Label* if_true = NULL; 2837 Label* if_true = NULL;
2838 Label* if_false = NULL; 2838 Label* if_false = NULL;
2839 Label* fall_through = NULL; 2839 Label* fall_through = NULL;
2840 context()->PrepareTest(&materialize_true, &materialize_false, 2840 context()->PrepareTest(&materialize_true, &materialize_false,
2841 &if_true, &if_false, &fall_through); 2841 &if_true, &if_false, &fall_through);
2842 2842
2843 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2843 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2844 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 2844 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
2845 Split(zero, if_true, if_false, fall_through); 2845 Split(zero, if_true, if_false, fall_through);
2846 2846
2847 context()->Plug(if_true, if_false); 2847 context()->Plug(if_true, if_false);
2848 } 2848 }
2849 2849
2850 2850
2851 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 2851 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2852 ZoneList<Expression*>* args = expr->arguments(); 2852 ZoneList<Expression*>* args = expr->arguments();
2853 ASSERT(args->length() == 1); 2853 DCHECK(args->length() == 1);
2854 2854
2855 VisitForAccumulatorValue(args->at(0)); 2855 VisitForAccumulatorValue(args->at(0));
2856 2856
2857 Label materialize_true, materialize_false; 2857 Label materialize_true, materialize_false;
2858 Label* if_true = NULL; 2858 Label* if_true = NULL;
2859 Label* if_false = NULL; 2859 Label* if_false = NULL;
2860 Label* fall_through = NULL; 2860 Label* fall_through = NULL;
2861 context()->PrepareTest(&materialize_true, &materialize_false, 2861 context()->PrepareTest(&materialize_true, &materialize_false,
2862 &if_true, &if_false, &fall_through); 2862 &if_true, &if_false, &fall_through);
2863 2863
(...skipping 11 matching lines...) Expand all
2875 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 2875 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2876 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2876 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2877 Split(below_equal, if_true, if_false, fall_through); 2877 Split(below_equal, if_true, if_false, fall_through);
2878 2878
2879 context()->Plug(if_true, if_false); 2879 context()->Plug(if_true, if_false);
2880 } 2880 }
2881 2881
2882 2882
2883 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 2883 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2884 ZoneList<Expression*>* args = expr->arguments(); 2884 ZoneList<Expression*>* args = expr->arguments();
2885 ASSERT(args->length() == 1); 2885 DCHECK(args->length() == 1);
2886 2886
2887 VisitForAccumulatorValue(args->at(0)); 2887 VisitForAccumulatorValue(args->at(0));
2888 2888
2889 Label materialize_true, materialize_false; 2889 Label materialize_true, materialize_false;
2890 Label* if_true = NULL; 2890 Label* if_true = NULL;
2891 Label* if_false = NULL; 2891 Label* if_false = NULL;
2892 Label* fall_through = NULL; 2892 Label* fall_through = NULL;
2893 context()->PrepareTest(&materialize_true, &materialize_false, 2893 context()->PrepareTest(&materialize_true, &materialize_false,
2894 &if_true, &if_false, &fall_through); 2894 &if_true, &if_false, &fall_through);
2895 2895
2896 __ JumpIfSmi(eax, if_false); 2896 __ JumpIfSmi(eax, if_false);
2897 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); 2897 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
2898 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2898 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2899 Split(above_equal, if_true, if_false, fall_through); 2899 Split(above_equal, if_true, if_false, fall_through);
2900 2900
2901 context()->Plug(if_true, if_false); 2901 context()->Plug(if_true, if_false);
2902 } 2902 }
2903 2903
2904 2904
2905 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 2905 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2906 ZoneList<Expression*>* args = expr->arguments(); 2906 ZoneList<Expression*>* args = expr->arguments();
2907 ASSERT(args->length() == 1); 2907 DCHECK(args->length() == 1);
2908 2908
2909 VisitForAccumulatorValue(args->at(0)); 2909 VisitForAccumulatorValue(args->at(0));
2910 2910
2911 Label materialize_true, materialize_false; 2911 Label materialize_true, materialize_false;
2912 Label* if_true = NULL; 2912 Label* if_true = NULL;
2913 Label* if_false = NULL; 2913 Label* if_false = NULL;
2914 Label* fall_through = NULL; 2914 Label* fall_through = NULL;
2915 context()->PrepareTest(&materialize_true, &materialize_false, 2915 context()->PrepareTest(&materialize_true, &materialize_false,
2916 &if_true, &if_false, &fall_through); 2916 &if_true, &if_false, &fall_through);
2917 2917
2918 __ JumpIfSmi(eax, if_false); 2918 __ JumpIfSmi(eax, if_false);
2919 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2919 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2920 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 2920 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2921 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); 2921 __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2922 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2922 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2923 Split(not_zero, if_true, if_false, fall_through); 2923 Split(not_zero, if_true, if_false, fall_through);
2924 2924
2925 context()->Plug(if_true, if_false); 2925 context()->Plug(if_true, if_false);
2926 } 2926 }
2927 2927
2928 2928
2929 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2929 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2930 CallRuntime* expr) { 2930 CallRuntime* expr) {
2931 ZoneList<Expression*>* args = expr->arguments(); 2931 ZoneList<Expression*>* args = expr->arguments();
2932 ASSERT(args->length() == 1); 2932 DCHECK(args->length() == 1);
2933 2933
2934 VisitForAccumulatorValue(args->at(0)); 2934 VisitForAccumulatorValue(args->at(0));
2935 2935
2936 Label materialize_true, materialize_false, skip_lookup; 2936 Label materialize_true, materialize_false, skip_lookup;
2937 Label* if_true = NULL; 2937 Label* if_true = NULL;
2938 Label* if_false = NULL; 2938 Label* if_false = NULL;
2939 Label* fall_through = NULL; 2939 Label* fall_through = NULL;
2940 context()->PrepareTest(&materialize_true, &materialize_false, 2940 context()->PrepareTest(&materialize_true, &materialize_false,
2941 &if_true, &if_false, &fall_through); 2941 &if_true, &if_false, &fall_through);
2942 2942
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3012 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 3012 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3013 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3013 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3014 Split(equal, if_true, if_false, fall_through); 3014 Split(equal, if_true, if_false, fall_through);
3015 3015
3016 context()->Plug(if_true, if_false); 3016 context()->Plug(if_true, if_false);
3017 } 3017 }
3018 3018
3019 3019
3020 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 3020 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3021 ZoneList<Expression*>* args = expr->arguments(); 3021 ZoneList<Expression*>* args = expr->arguments();
3022 ASSERT(args->length() == 1); 3022 DCHECK(args->length() == 1);
3023 3023
3024 VisitForAccumulatorValue(args->at(0)); 3024 VisitForAccumulatorValue(args->at(0));
3025 3025
3026 Label materialize_true, materialize_false; 3026 Label materialize_true, materialize_false;
3027 Label* if_true = NULL; 3027 Label* if_true = NULL;
3028 Label* if_false = NULL; 3028 Label* if_false = NULL;
3029 Label* fall_through = NULL; 3029 Label* fall_through = NULL;
3030 context()->PrepareTest(&materialize_true, &materialize_false, 3030 context()->PrepareTest(&materialize_true, &materialize_false,
3031 &if_true, &if_false, &fall_through); 3031 &if_true, &if_false, &fall_through);
3032 3032
3033 __ JumpIfSmi(eax, if_false); 3033 __ JumpIfSmi(eax, if_false);
3034 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 3034 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3035 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3035 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3036 Split(equal, if_true, if_false, fall_through); 3036 Split(equal, if_true, if_false, fall_through);
3037 3037
3038 context()->Plug(if_true, if_false); 3038 context()->Plug(if_true, if_false);
3039 } 3039 }
3040 3040
3041 3041
3042 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { 3042 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3043 ZoneList<Expression*>* args = expr->arguments(); 3043 ZoneList<Expression*>* args = expr->arguments();
3044 ASSERT(args->length() == 1); 3044 DCHECK(args->length() == 1);
3045 3045
3046 VisitForAccumulatorValue(args->at(0)); 3046 VisitForAccumulatorValue(args->at(0));
3047 3047
3048 Label materialize_true, materialize_false; 3048 Label materialize_true, materialize_false;
3049 Label* if_true = NULL; 3049 Label* if_true = NULL;
3050 Label* if_false = NULL; 3050 Label* if_false = NULL;
3051 Label* fall_through = NULL; 3051 Label* fall_through = NULL;
3052 context()->PrepareTest(&materialize_true, &materialize_false, 3052 context()->PrepareTest(&materialize_true, &materialize_false,
3053 &if_true, &if_false, &fall_through); 3053 &if_true, &if_false, &fall_through);
3054 3054
3055 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); 3055 Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
3056 __ CheckMap(eax, map, if_false, DO_SMI_CHECK); 3056 __ CheckMap(eax, map, if_false, DO_SMI_CHECK);
3057 // Check if the exponent half is 0x80000000. Comparing against 1 and 3057 // Check if the exponent half is 0x80000000. Comparing against 1 and
3058 // checking for overflow is the shortest possible encoding. 3058 // checking for overflow is the shortest possible encoding.
3059 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1)); 3059 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1));
3060 __ j(no_overflow, if_false); 3060 __ j(no_overflow, if_false);
3061 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0)); 3061 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0));
3062 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3062 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3063 Split(equal, if_true, if_false, fall_through); 3063 Split(equal, if_true, if_false, fall_through);
3064 3064
3065 context()->Plug(if_true, if_false); 3065 context()->Plug(if_true, if_false);
3066 } 3066 }
3067 3067
3068 3068
3069 3069
3070 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 3070 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3071 ZoneList<Expression*>* args = expr->arguments(); 3071 ZoneList<Expression*>* args = expr->arguments();
3072 ASSERT(args->length() == 1); 3072 DCHECK(args->length() == 1);
3073 3073
3074 VisitForAccumulatorValue(args->at(0)); 3074 VisitForAccumulatorValue(args->at(0));
3075 3075
3076 Label materialize_true, materialize_false; 3076 Label materialize_true, materialize_false;
3077 Label* if_true = NULL; 3077 Label* if_true = NULL;
3078 Label* if_false = NULL; 3078 Label* if_false = NULL;
3079 Label* fall_through = NULL; 3079 Label* fall_through = NULL;
3080 context()->PrepareTest(&materialize_true, &materialize_false, 3080 context()->PrepareTest(&materialize_true, &materialize_false,
3081 &if_true, &if_false, &fall_through); 3081 &if_true, &if_false, &fall_through);
3082 3082
3083 __ JumpIfSmi(eax, if_false); 3083 __ JumpIfSmi(eax, if_false);
3084 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 3084 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
3085 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3085 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3086 Split(equal, if_true, if_false, fall_through); 3086 Split(equal, if_true, if_false, fall_through);
3087 3087
3088 context()->Plug(if_true, if_false); 3088 context()->Plug(if_true, if_false);
3089 } 3089 }
3090 3090
3091 3091
3092 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 3092 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3093 ZoneList<Expression*>* args = expr->arguments(); 3093 ZoneList<Expression*>* args = expr->arguments();
3094 ASSERT(args->length() == 1); 3094 DCHECK(args->length() == 1);
3095 3095
3096 VisitForAccumulatorValue(args->at(0)); 3096 VisitForAccumulatorValue(args->at(0));
3097 3097
3098 Label materialize_true, materialize_false; 3098 Label materialize_true, materialize_false;
3099 Label* if_true = NULL; 3099 Label* if_true = NULL;
3100 Label* if_false = NULL; 3100 Label* if_false = NULL;
3101 Label* fall_through = NULL; 3101 Label* fall_through = NULL;
3102 context()->PrepareTest(&materialize_true, &materialize_false, 3102 context()->PrepareTest(&materialize_true, &materialize_false,
3103 &if_true, &if_false, &fall_through); 3103 &if_true, &if_false, &fall_through);
3104 3104
3105 __ JumpIfSmi(eax, if_false); 3105 __ JumpIfSmi(eax, if_false);
3106 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); 3106 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
3107 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3107 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3108 Split(equal, if_true, if_false, fall_through); 3108 Split(equal, if_true, if_false, fall_through);
3109 3109
3110 context()->Plug(if_true, if_false); 3110 context()->Plug(if_true, if_false);
3111 } 3111 }
3112 3112
3113 3113
3114 3114
3115 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 3115 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3116 ASSERT(expr->arguments()->length() == 0); 3116 DCHECK(expr->arguments()->length() == 0);
3117 3117
3118 Label materialize_true, materialize_false; 3118 Label materialize_true, materialize_false;
3119 Label* if_true = NULL; 3119 Label* if_true = NULL;
3120 Label* if_false = NULL; 3120 Label* if_false = NULL;
3121 Label* fall_through = NULL; 3121 Label* fall_through = NULL;
3122 context()->PrepareTest(&materialize_true, &materialize_false, 3122 context()->PrepareTest(&materialize_true, &materialize_false,
3123 &if_true, &if_false, &fall_through); 3123 &if_true, &if_false, &fall_through);
3124 3124
3125 // Get the frame pointer for the calling frame. 3125 // Get the frame pointer for the calling frame.
3126 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3126 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
(...skipping 11 matching lines...) Expand all
3138 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 3138 Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
3139 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3139 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3140 Split(equal, if_true, if_false, fall_through); 3140 Split(equal, if_true, if_false, fall_through);
3141 3141
3142 context()->Plug(if_true, if_false); 3142 context()->Plug(if_true, if_false);
3143 } 3143 }
3144 3144
3145 3145
3146 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 3146 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3147 ZoneList<Expression*>* args = expr->arguments(); 3147 ZoneList<Expression*>* args = expr->arguments();
3148 ASSERT(args->length() == 2); 3148 DCHECK(args->length() == 2);
3149 3149
3150 // Load the two objects into registers and perform the comparison. 3150 // Load the two objects into registers and perform the comparison.
3151 VisitForStackValue(args->at(0)); 3151 VisitForStackValue(args->at(0));
3152 VisitForAccumulatorValue(args->at(1)); 3152 VisitForAccumulatorValue(args->at(1));
3153 3153
3154 Label materialize_true, materialize_false; 3154 Label materialize_true, materialize_false;
3155 Label* if_true = NULL; 3155 Label* if_true = NULL;
3156 Label* if_false = NULL; 3156 Label* if_false = NULL;
3157 Label* fall_through = NULL; 3157 Label* fall_through = NULL;
3158 context()->PrepareTest(&materialize_true, &materialize_false, 3158 context()->PrepareTest(&materialize_true, &materialize_false,
3159 &if_true, &if_false, &fall_through); 3159 &if_true, &if_false, &fall_through);
3160 3160
3161 __ pop(ebx); 3161 __ pop(ebx);
3162 __ cmp(eax, ebx); 3162 __ cmp(eax, ebx);
3163 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3163 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3164 Split(equal, if_true, if_false, fall_through); 3164 Split(equal, if_true, if_false, fall_through);
3165 3165
3166 context()->Plug(if_true, if_false); 3166 context()->Plug(if_true, if_false);
3167 } 3167 }
3168 3168
3169 3169
3170 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { 3170 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3171 ZoneList<Expression*>* args = expr->arguments(); 3171 ZoneList<Expression*>* args = expr->arguments();
3172 ASSERT(args->length() == 1); 3172 DCHECK(args->length() == 1);
3173 3173
3174 // ArgumentsAccessStub expects the key in edx and the formal 3174 // ArgumentsAccessStub expects the key in edx and the formal
3175 // parameter count in eax. 3175 // parameter count in eax.
3176 VisitForAccumulatorValue(args->at(0)); 3176 VisitForAccumulatorValue(args->at(0));
3177 __ mov(edx, eax); 3177 __ mov(edx, eax);
3178 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); 3178 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
3179 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); 3179 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3180 __ CallStub(&stub); 3180 __ CallStub(&stub);
3181 context()->Plug(eax); 3181 context()->Plug(eax);
3182 } 3182 }
3183 3183
3184 3184
3185 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3185 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3186 ASSERT(expr->arguments()->length() == 0); 3186 DCHECK(expr->arguments()->length() == 0);
3187 3187
3188 Label exit; 3188 Label exit;
3189 // Get the number of formal parameters. 3189 // Get the number of formal parameters.
3190 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); 3190 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
3191 3191
3192 // Check if the calling frame is an arguments adaptor frame. 3192 // Check if the calling frame is an arguments adaptor frame.
3193 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3193 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3194 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 3194 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
3195 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3195 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3196 __ j(not_equal, &exit); 3196 __ j(not_equal, &exit);
3197 3197
3198 // Arguments adaptor case: Read the arguments length from the 3198 // Arguments adaptor case: Read the arguments length from the
3199 // adaptor frame. 3199 // adaptor frame.
3200 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3200 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3201 3201
3202 __ bind(&exit); 3202 __ bind(&exit);
3203 __ AssertSmi(eax); 3203 __ AssertSmi(eax);
3204 context()->Plug(eax); 3204 context()->Plug(eax);
3205 } 3205 }
3206 3206
3207 3207
3208 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 3208 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3209 ZoneList<Expression*>* args = expr->arguments(); 3209 ZoneList<Expression*>* args = expr->arguments();
3210 ASSERT(args->length() == 1); 3210 DCHECK(args->length() == 1);
3211 Label done, null, function, non_function_constructor; 3211 Label done, null, function, non_function_constructor;
3212 3212
3213 VisitForAccumulatorValue(args->at(0)); 3213 VisitForAccumulatorValue(args->at(0));
3214 3214
3215 // If the object is a smi, we return null. 3215 // If the object is a smi, we return null.
3216 __ JumpIfSmi(eax, &null); 3216 __ JumpIfSmi(eax, &null);
3217 3217
3218 // Check that the object is a JS object but take special care of JS 3218 // Check that the object is a JS object but take special care of JS
3219 // functions to make sure they have 'Function' as their class. 3219 // functions to make sure they have 'Function' as their class.
3220 // Assume that there are only two callable types, and one of them is at 3220 // Assume that there are only two callable types, and one of them is at
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 __ bind(&done); 3263 __ bind(&done);
3264 3264
3265 context()->Plug(eax); 3265 context()->Plug(eax);
3266 } 3266 }
3267 3267
3268 3268
3269 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3269 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3270 // Load the arguments on the stack and call the stub. 3270 // Load the arguments on the stack and call the stub.
3271 SubStringStub stub(isolate()); 3271 SubStringStub stub(isolate());
3272 ZoneList<Expression*>* args = expr->arguments(); 3272 ZoneList<Expression*>* args = expr->arguments();
3273 ASSERT(args->length() == 3); 3273 DCHECK(args->length() == 3);
3274 VisitForStackValue(args->at(0)); 3274 VisitForStackValue(args->at(0));
3275 VisitForStackValue(args->at(1)); 3275 VisitForStackValue(args->at(1));
3276 VisitForStackValue(args->at(2)); 3276 VisitForStackValue(args->at(2));
3277 __ CallStub(&stub); 3277 __ CallStub(&stub);
3278 context()->Plug(eax); 3278 context()->Plug(eax);
3279 } 3279 }
3280 3280
3281 3281
3282 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 3282 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3283 // Load the arguments on the stack and call the stub. 3283 // Load the arguments on the stack and call the stub.
3284 RegExpExecStub stub(isolate()); 3284 RegExpExecStub stub(isolate());
3285 ZoneList<Expression*>* args = expr->arguments(); 3285 ZoneList<Expression*>* args = expr->arguments();
3286 ASSERT(args->length() == 4); 3286 DCHECK(args->length() == 4);
3287 VisitForStackValue(args->at(0)); 3287 VisitForStackValue(args->at(0));
3288 VisitForStackValue(args->at(1)); 3288 VisitForStackValue(args->at(1));
3289 VisitForStackValue(args->at(2)); 3289 VisitForStackValue(args->at(2));
3290 VisitForStackValue(args->at(3)); 3290 VisitForStackValue(args->at(3));
3291 __ CallStub(&stub); 3291 __ CallStub(&stub);
3292 context()->Plug(eax); 3292 context()->Plug(eax);
3293 } 3293 }
3294 3294
3295 3295
3296 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 3296 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3297 ZoneList<Expression*>* args = expr->arguments(); 3297 ZoneList<Expression*>* args = expr->arguments();
3298 ASSERT(args->length() == 1); 3298 DCHECK(args->length() == 1);
3299 3299
3300 VisitForAccumulatorValue(args->at(0)); // Load the object. 3300 VisitForAccumulatorValue(args->at(0)); // Load the object.
3301 3301
3302 Label done; 3302 Label done;
3303 // If the object is a smi return the object. 3303 // If the object is a smi return the object.
3304 __ JumpIfSmi(eax, &done, Label::kNear); 3304 __ JumpIfSmi(eax, &done, Label::kNear);
3305 // If the object is not a value type, return the object. 3305 // If the object is not a value type, return the object.
3306 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); 3306 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
3307 __ j(not_equal, &done, Label::kNear); 3307 __ j(not_equal, &done, Label::kNear);
3308 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 3308 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
3309 3309
3310 __ bind(&done); 3310 __ bind(&done);
3311 context()->Plug(eax); 3311 context()->Plug(eax);
3312 } 3312 }
3313 3313
3314 3314
3315 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { 3315 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3316 ZoneList<Expression*>* args = expr->arguments(); 3316 ZoneList<Expression*>* args = expr->arguments();
3317 ASSERT(args->length() == 2); 3317 DCHECK(args->length() == 2);
3318 ASSERT_NE(NULL, args->at(1)->AsLiteral()); 3318 DCHECK_NE(NULL, args->at(1)->AsLiteral());
3319 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 3319 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3320 3320
3321 VisitForAccumulatorValue(args->at(0)); // Load the object. 3321 VisitForAccumulatorValue(args->at(0)); // Load the object.
3322 3322
3323 Label runtime, done, not_date_object; 3323 Label runtime, done, not_date_object;
3324 Register object = eax; 3324 Register object = eax;
3325 Register result = eax; 3325 Register result = eax;
3326 Register scratch = ecx; 3326 Register scratch = ecx;
3327 3327
3328 __ JumpIfSmi(object, &not_date_object); 3328 __ JumpIfSmi(object, &not_date_object);
(...skipping 23 matching lines...) Expand all
3352 3352
3353 __ bind(&not_date_object); 3353 __ bind(&not_date_object);
3354 __ CallRuntime(Runtime::kThrowNotDateError, 0); 3354 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3355 __ bind(&done); 3355 __ bind(&done);
3356 context()->Plug(result); 3356 context()->Plug(result);
3357 } 3357 }
3358 3358
3359 3359
3360 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3360 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3361 ZoneList<Expression*>* args = expr->arguments(); 3361 ZoneList<Expression*>* args = expr->arguments();
3362 ASSERT_EQ(3, args->length()); 3362 DCHECK_EQ(3, args->length());
3363 3363
3364 Register string = eax; 3364 Register string = eax;
3365 Register index = ebx; 3365 Register index = ebx;
3366 Register value = ecx; 3366 Register value = ecx;
3367 3367
3368 VisitForStackValue(args->at(1)); // index 3368 VisitForStackValue(args->at(1)); // index
3369 VisitForStackValue(args->at(2)); // value 3369 VisitForStackValue(args->at(2)); // value
3370 VisitForAccumulatorValue(args->at(0)); // string 3370 VisitForAccumulatorValue(args->at(0)); // string
3371 3371
3372 __ pop(value); 3372 __ pop(value);
(...skipping 15 matching lines...) Expand all
3388 } 3388 }
3389 3389
3390 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), 3390 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
3391 value); 3391 value);
3392 context()->Plug(string); 3392 context()->Plug(string);
3393 } 3393 }
3394 3394
3395 3395
3396 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3396 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3397 ZoneList<Expression*>* args = expr->arguments(); 3397 ZoneList<Expression*>* args = expr->arguments();
3398 ASSERT_EQ(3, args->length()); 3398 DCHECK_EQ(3, args->length());
3399 3399
3400 Register string = eax; 3400 Register string = eax;
3401 Register index = ebx; 3401 Register index = ebx;
3402 Register value = ecx; 3402 Register value = ecx;
3403 3403
3404 VisitForStackValue(args->at(1)); // index 3404 VisitForStackValue(args->at(1)); // index
3405 VisitForStackValue(args->at(2)); // value 3405 VisitForStackValue(args->at(2)); // value
3406 VisitForAccumulatorValue(args->at(0)); // string 3406 VisitForAccumulatorValue(args->at(0)); // string
3407 __ pop(value); 3407 __ pop(value);
3408 __ pop(index); 3408 __ pop(index);
(...skipping 13 matching lines...) Expand all
3422 // No need to untag a smi for two-byte addressing. 3422 // No need to untag a smi for two-byte addressing.
3423 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), 3423 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
3424 value); 3424 value);
3425 context()->Plug(string); 3425 context()->Plug(string);
3426 } 3426 }
3427 3427
3428 3428
3429 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3429 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3430 // Load the arguments on the stack and call the runtime function. 3430 // Load the arguments on the stack and call the runtime function.
3431 ZoneList<Expression*>* args = expr->arguments(); 3431 ZoneList<Expression*>* args = expr->arguments();
3432 ASSERT(args->length() == 2); 3432 DCHECK(args->length() == 2);
3433 VisitForStackValue(args->at(0)); 3433 VisitForStackValue(args->at(0));
3434 VisitForStackValue(args->at(1)); 3434 VisitForStackValue(args->at(1));
3435 3435
3436 MathPowStub stub(isolate(), MathPowStub::ON_STACK); 3436 MathPowStub stub(isolate(), MathPowStub::ON_STACK);
3437 __ CallStub(&stub); 3437 __ CallStub(&stub);
3438 context()->Plug(eax); 3438 context()->Plug(eax);
3439 } 3439 }
3440 3440
3441 3441
3442 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 3442 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3443 ZoneList<Expression*>* args = expr->arguments(); 3443 ZoneList<Expression*>* args = expr->arguments();
3444 ASSERT(args->length() == 2); 3444 DCHECK(args->length() == 2);
3445 3445
3446 VisitForStackValue(args->at(0)); // Load the object. 3446 VisitForStackValue(args->at(0)); // Load the object.
3447 VisitForAccumulatorValue(args->at(1)); // Load the value. 3447 VisitForAccumulatorValue(args->at(1)); // Load the value.
3448 __ pop(ebx); // eax = value. ebx = object. 3448 __ pop(ebx); // eax = value. ebx = object.
3449 3449
3450 Label done; 3450 Label done;
3451 // If the object is a smi, return the value. 3451 // If the object is a smi, return the value.
3452 __ JumpIfSmi(ebx, &done, Label::kNear); 3452 __ JumpIfSmi(ebx, &done, Label::kNear);
3453 3453
3454 // If the object is not a value type, return the value. 3454 // If the object is not a value type, return the value.
3455 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 3455 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
3456 __ j(not_equal, &done, Label::kNear); 3456 __ j(not_equal, &done, Label::kNear);
3457 3457
3458 // Store the value. 3458 // Store the value.
3459 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 3459 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
3460 3460
3461 // Update the write barrier. Save the value as it will be 3461 // Update the write barrier. Save the value as it will be
3462 // overwritten by the write barrier code and is needed afterward. 3462 // overwritten by the write barrier code and is needed afterward.
3463 __ mov(edx, eax); 3463 __ mov(edx, eax);
3464 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); 3464 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
3465 3465
3466 __ bind(&done); 3466 __ bind(&done);
3467 context()->Plug(eax); 3467 context()->Plug(eax);
3468 } 3468 }
3469 3469
3470 3470
3471 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 3471 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3472 ZoneList<Expression*>* args = expr->arguments(); 3472 ZoneList<Expression*>* args = expr->arguments();
3473 ASSERT_EQ(args->length(), 1); 3473 DCHECK_EQ(args->length(), 1);
3474 3474
3475 // Load the argument into eax and call the stub. 3475 // Load the argument into eax and call the stub.
3476 VisitForAccumulatorValue(args->at(0)); 3476 VisitForAccumulatorValue(args->at(0));
3477 3477
3478 NumberToStringStub stub(isolate()); 3478 NumberToStringStub stub(isolate());
3479 __ CallStub(&stub); 3479 __ CallStub(&stub);
3480 context()->Plug(eax); 3480 context()->Plug(eax);
3481 } 3481 }
3482 3482
3483 3483
3484 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 3484 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3485 ZoneList<Expression*>* args = expr->arguments(); 3485 ZoneList<Expression*>* args = expr->arguments();
3486 ASSERT(args->length() == 1); 3486 DCHECK(args->length() == 1);
3487 3487
3488 VisitForAccumulatorValue(args->at(0)); 3488 VisitForAccumulatorValue(args->at(0));
3489 3489
3490 Label done; 3490 Label done;
3491 StringCharFromCodeGenerator generator(eax, ebx); 3491 StringCharFromCodeGenerator generator(eax, ebx);
3492 generator.GenerateFast(masm_); 3492 generator.GenerateFast(masm_);
3493 __ jmp(&done); 3493 __ jmp(&done);
3494 3494
3495 NopRuntimeCallHelper call_helper; 3495 NopRuntimeCallHelper call_helper;
3496 generator.GenerateSlow(masm_, call_helper); 3496 generator.GenerateSlow(masm_, call_helper);
3497 3497
3498 __ bind(&done); 3498 __ bind(&done);
3499 context()->Plug(ebx); 3499 context()->Plug(ebx);
3500 } 3500 }
3501 3501
3502 3502
3503 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 3503 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3504 ZoneList<Expression*>* args = expr->arguments(); 3504 ZoneList<Expression*>* args = expr->arguments();
3505 ASSERT(args->length() == 2); 3505 DCHECK(args->length() == 2);
3506 3506
3507 VisitForStackValue(args->at(0)); 3507 VisitForStackValue(args->at(0));
3508 VisitForAccumulatorValue(args->at(1)); 3508 VisitForAccumulatorValue(args->at(1));
3509 3509
3510 Register object = ebx; 3510 Register object = ebx;
3511 Register index = eax; 3511 Register index = eax;
3512 Register result = edx; 3512 Register result = edx;
3513 3513
3514 __ pop(object); 3514 __ pop(object);
3515 3515
(...skipping 25 matching lines...) Expand all
3541 NopRuntimeCallHelper call_helper; 3541 NopRuntimeCallHelper call_helper;
3542 generator.GenerateSlow(masm_, call_helper); 3542 generator.GenerateSlow(masm_, call_helper);
3543 3543
3544 __ bind(&done); 3544 __ bind(&done);
3545 context()->Plug(result); 3545 context()->Plug(result);
3546 } 3546 }
3547 3547
3548 3548
3549 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 3549 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3550 ZoneList<Expression*>* args = expr->arguments(); 3550 ZoneList<Expression*>* args = expr->arguments();
3551 ASSERT(args->length() == 2); 3551 DCHECK(args->length() == 2);
3552 3552
3553 VisitForStackValue(args->at(0)); 3553 VisitForStackValue(args->at(0));
3554 VisitForAccumulatorValue(args->at(1)); 3554 VisitForAccumulatorValue(args->at(1));
3555 3555
3556 Register object = ebx; 3556 Register object = ebx;
3557 Register index = eax; 3557 Register index = eax;
3558 Register scratch = edx; 3558 Register scratch = edx;
3559 Register result = eax; 3559 Register result = eax;
3560 3560
3561 __ pop(object); 3561 __ pop(object);
(...skipping 27 matching lines...) Expand all
3589 NopRuntimeCallHelper call_helper; 3589 NopRuntimeCallHelper call_helper;
3590 generator.GenerateSlow(masm_, call_helper); 3590 generator.GenerateSlow(masm_, call_helper);
3591 3591
3592 __ bind(&done); 3592 __ bind(&done);
3593 context()->Plug(result); 3593 context()->Plug(result);
3594 } 3594 }
3595 3595
3596 3596
3597 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3597 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3598 ZoneList<Expression*>* args = expr->arguments(); 3598 ZoneList<Expression*>* args = expr->arguments();
3599 ASSERT_EQ(2, args->length()); 3599 DCHECK_EQ(2, args->length());
3600 VisitForStackValue(args->at(0)); 3600 VisitForStackValue(args->at(0));
3601 VisitForAccumulatorValue(args->at(1)); 3601 VisitForAccumulatorValue(args->at(1));
3602 3602
3603 __ pop(edx); 3603 __ pop(edx);
3604 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); 3604 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3605 __ CallStub(&stub); 3605 __ CallStub(&stub);
3606 context()->Plug(eax); 3606 context()->Plug(eax);
3607 } 3607 }
3608 3608
3609 3609
3610 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3610 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3611 ZoneList<Expression*>* args = expr->arguments(); 3611 ZoneList<Expression*>* args = expr->arguments();
3612 ASSERT_EQ(2, args->length()); 3612 DCHECK_EQ(2, args->length());
3613 3613
3614 VisitForStackValue(args->at(0)); 3614 VisitForStackValue(args->at(0));
3615 VisitForStackValue(args->at(1)); 3615 VisitForStackValue(args->at(1));
3616 3616
3617 StringCompareStub stub(isolate()); 3617 StringCompareStub stub(isolate());
3618 __ CallStub(&stub); 3618 __ CallStub(&stub);
3619 context()->Plug(eax); 3619 context()->Plug(eax);
3620 } 3620 }
3621 3621
3622 3622
3623 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 3623 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3624 ZoneList<Expression*>* args = expr->arguments(); 3624 ZoneList<Expression*>* args = expr->arguments();
3625 ASSERT(args->length() >= 2); 3625 DCHECK(args->length() >= 2);
3626 3626
3627 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3627 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3628 for (int i = 0; i < arg_count + 1; ++i) { 3628 for (int i = 0; i < arg_count + 1; ++i) {
3629 VisitForStackValue(args->at(i)); 3629 VisitForStackValue(args->at(i));
3630 } 3630 }
3631 VisitForAccumulatorValue(args->last()); // Function. 3631 VisitForAccumulatorValue(args->last()); // Function.
3632 3632
3633 Label runtime, done; 3633 Label runtime, done;
3634 // Check for non-function argument (including proxy). 3634 // Check for non-function argument (including proxy).
3635 __ JumpIfSmi(eax, &runtime); 3635 __ JumpIfSmi(eax, &runtime);
(...skipping 13 matching lines...) Expand all
3649 __ bind(&done); 3649 __ bind(&done);
3650 3650
3651 context()->Plug(eax); 3651 context()->Plug(eax);
3652 } 3652 }
3653 3653
3654 3654
3655 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3655 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3656 // Load the arguments on the stack and call the stub. 3656 // Load the arguments on the stack and call the stub.
3657 RegExpConstructResultStub stub(isolate()); 3657 RegExpConstructResultStub stub(isolate());
3658 ZoneList<Expression*>* args = expr->arguments(); 3658 ZoneList<Expression*>* args = expr->arguments();
3659 ASSERT(args->length() == 3); 3659 DCHECK(args->length() == 3);
3660 VisitForStackValue(args->at(0)); 3660 VisitForStackValue(args->at(0));
3661 VisitForStackValue(args->at(1)); 3661 VisitForStackValue(args->at(1));
3662 VisitForAccumulatorValue(args->at(2)); 3662 VisitForAccumulatorValue(args->at(2));
3663 __ pop(ebx); 3663 __ pop(ebx);
3664 __ pop(ecx); 3664 __ pop(ecx);
3665 __ CallStub(&stub); 3665 __ CallStub(&stub);
3666 context()->Plug(eax); 3666 context()->Plug(eax);
3667 } 3667 }
3668 3668
3669 3669
3670 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3670 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3671 ZoneList<Expression*>* args = expr->arguments(); 3671 ZoneList<Expression*>* args = expr->arguments();
3672 ASSERT_EQ(2, args->length()); 3672 DCHECK_EQ(2, args->length());
3673 3673
3674 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3674 DCHECK_NE(NULL, args->at(0)->AsLiteral());
3675 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); 3675 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3676 3676
3677 Handle<FixedArray> jsfunction_result_caches( 3677 Handle<FixedArray> jsfunction_result_caches(
3678 isolate()->native_context()->jsfunction_result_caches()); 3678 isolate()->native_context()->jsfunction_result_caches());
3679 if (jsfunction_result_caches->length() <= cache_id) { 3679 if (jsfunction_result_caches->length() <= cache_id) {
3680 __ Abort(kAttemptToUseUndefinedCache); 3680 __ Abort(kAttemptToUseUndefinedCache);
3681 __ mov(eax, isolate()->factory()->undefined_value()); 3681 __ mov(eax, isolate()->factory()->undefined_value());
3682 context()->Plug(eax); 3682 context()->Plug(eax);
3683 return; 3683 return;
3684 } 3684 }
(...skipping 26 matching lines...) Expand all
3711 __ push(key); 3711 __ push(key);
3712 __ CallRuntime(Runtime::kGetFromCache, 2); 3712 __ CallRuntime(Runtime::kGetFromCache, 2);
3713 3713
3714 __ bind(&done); 3714 __ bind(&done);
3715 context()->Plug(eax); 3715 context()->Plug(eax);
3716 } 3716 }
3717 3717
3718 3718
3719 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3719 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3720 ZoneList<Expression*>* args = expr->arguments(); 3720 ZoneList<Expression*>* args = expr->arguments();
3721 ASSERT(args->length() == 1); 3721 DCHECK(args->length() == 1);
3722 3722
3723 VisitForAccumulatorValue(args->at(0)); 3723 VisitForAccumulatorValue(args->at(0));
3724 3724
3725 __ AssertString(eax); 3725 __ AssertString(eax);
3726 3726
3727 Label materialize_true, materialize_false; 3727 Label materialize_true, materialize_false;
3728 Label* if_true = NULL; 3728 Label* if_true = NULL;
3729 Label* if_false = NULL; 3729 Label* if_false = NULL;
3730 Label* fall_through = NULL; 3730 Label* fall_through = NULL;
3731 context()->PrepareTest(&materialize_true, &materialize_false, 3731 context()->PrepareTest(&materialize_true, &materialize_false,
3732 &if_true, &if_false, &fall_through); 3732 &if_true, &if_false, &fall_through);
3733 3733
3734 __ test(FieldOperand(eax, String::kHashFieldOffset), 3734 __ test(FieldOperand(eax, String::kHashFieldOffset),
3735 Immediate(String::kContainsCachedArrayIndexMask)); 3735 Immediate(String::kContainsCachedArrayIndexMask));
3736 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3736 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3737 Split(zero, if_true, if_false, fall_through); 3737 Split(zero, if_true, if_false, fall_through);
3738 3738
3739 context()->Plug(if_true, if_false); 3739 context()->Plug(if_true, if_false);
3740 } 3740 }
3741 3741
3742 3742
3743 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 3743 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3744 ZoneList<Expression*>* args = expr->arguments(); 3744 ZoneList<Expression*>* args = expr->arguments();
3745 ASSERT(args->length() == 1); 3745 DCHECK(args->length() == 1);
3746 VisitForAccumulatorValue(args->at(0)); 3746 VisitForAccumulatorValue(args->at(0));
3747 3747
3748 __ AssertString(eax); 3748 __ AssertString(eax);
3749 3749
3750 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 3750 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3751 __ IndexFromHash(eax, eax); 3751 __ IndexFromHash(eax, eax);
3752 3752
3753 context()->Plug(eax); 3753 context()->Plug(eax);
3754 } 3754 }
3755 3755
3756 3756
3757 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { 3757 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3758 Label bailout, done, one_char_separator, long_separator, 3758 Label bailout, done, one_char_separator, long_separator,
3759 non_trivial_array, not_size_one_array, loop, 3759 non_trivial_array, not_size_one_array, loop,
3760 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 3760 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3761 3761
3762 ZoneList<Expression*>* args = expr->arguments(); 3762 ZoneList<Expression*>* args = expr->arguments();
3763 ASSERT(args->length() == 2); 3763 DCHECK(args->length() == 2);
3764 // We will leave the separator on the stack until the end of the function. 3764 // We will leave the separator on the stack until the end of the function.
3765 VisitForStackValue(args->at(1)); 3765 VisitForStackValue(args->at(1));
3766 // Load this to eax (= array) 3766 // Load this to eax (= array)
3767 VisitForAccumulatorValue(args->at(0)); 3767 VisitForAccumulatorValue(args->at(0));
3768 // All aliases of the same register have disjoint lifetimes. 3768 // All aliases of the same register have disjoint lifetimes.
3769 Register array = eax; 3769 Register array = eax;
3770 Register elements = no_reg; // Will be eax. 3770 Register elements = no_reg; // Will be eax.
3771 3771
3772 Register index = edx; 3772 Register index = edx;
3773 3773
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
4012 __ mov(eax, result_operand); 4012 __ mov(eax, result_operand);
4013 // Drop temp values from the stack, and restore context register. 4013 // Drop temp values from the stack, and restore context register.
4014 __ add(esp, Immediate(3 * kPointerSize)); 4014 __ add(esp, Immediate(3 * kPointerSize));
4015 4015
4016 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4016 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4017 context()->Plug(eax); 4017 context()->Plug(eax);
4018 } 4018 }
4019 4019
4020 4020
4021 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 4021 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4022 ASSERT(expr->arguments()->length() == 0); 4022 DCHECK(expr->arguments()->length() == 0);
4023 ExternalReference debug_is_active = 4023 ExternalReference debug_is_active =
4024 ExternalReference::debug_is_active_address(isolate()); 4024 ExternalReference::debug_is_active_address(isolate());
4025 __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); 4025 __ movzx_b(eax, Operand::StaticVariable(debug_is_active));
4026 __ SmiTag(eax); 4026 __ SmiTag(eax);
4027 context()->Plug(eax); 4027 context()->Plug(eax);
4028 } 4028 }
4029 4029
4030 4030
4031 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4031 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4032 if (expr->function() != NULL && 4032 if (expr->function() != NULL &&
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
4100 if (property != NULL) { 4100 if (property != NULL) {
4101 VisitForStackValue(property->obj()); 4101 VisitForStackValue(property->obj());
4102 VisitForStackValue(property->key()); 4102 VisitForStackValue(property->key());
4103 __ push(Immediate(Smi::FromInt(strict_mode()))); 4103 __ push(Immediate(Smi::FromInt(strict_mode())));
4104 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4104 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4105 context()->Plug(eax); 4105 context()->Plug(eax);
4106 } else if (proxy != NULL) { 4106 } else if (proxy != NULL) {
4107 Variable* var = proxy->var(); 4107 Variable* var = proxy->var();
4108 // Delete of an unqualified identifier is disallowed in strict mode 4108 // Delete of an unqualified identifier is disallowed in strict mode
4109 // but "delete this" is allowed. 4109 // but "delete this" is allowed.
4110 ASSERT(strict_mode() == SLOPPY || var->is_this()); 4110 DCHECK(strict_mode() == SLOPPY || var->is_this());
4111 if (var->IsUnallocated()) { 4111 if (var->IsUnallocated()) {
4112 __ push(GlobalObjectOperand()); 4112 __ push(GlobalObjectOperand());
4113 __ push(Immediate(var->name())); 4113 __ push(Immediate(var->name()));
4114 __ push(Immediate(Smi::FromInt(SLOPPY))); 4114 __ push(Immediate(Smi::FromInt(SLOPPY)));
4115 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4115 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4116 context()->Plug(eax); 4116 context()->Plug(eax);
4117 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4117 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4118 // Result of deleting non-global variables is false. 'this' is 4118 // Result of deleting non-global variables is false. 'this' is
4119 // not really a variable, though we implement it as one. The 4119 // not really a variable, though we implement it as one. The
4120 // subexpression does not have side effects. 4120 // subexpression does not have side effects.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4155 VisitForControl(expr->expression(), 4155 VisitForControl(expr->expression(),
4156 test->false_label(), 4156 test->false_label(),
4157 test->true_label(), 4157 test->true_label(),
4158 test->fall_through()); 4158 test->fall_through());
4159 context()->Plug(test->true_label(), test->false_label()); 4159 context()->Plug(test->true_label(), test->false_label());
4160 } else { 4160 } else {
4161 // We handle value contexts explicitly rather than simply visiting 4161 // We handle value contexts explicitly rather than simply visiting
4162 // for control and plugging the control flow into the context, 4162 // for control and plugging the control flow into the context,
4163 // 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
4164 // for the optimizing compiler. 4164 // for the optimizing compiler.
4165 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); 4165 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
4166 Label materialize_true, materialize_false, done; 4166 Label materialize_true, materialize_false, done;
4167 VisitForControl(expr->expression(), 4167 VisitForControl(expr->expression(),
4168 &materialize_false, 4168 &materialize_false,
4169 &materialize_true, 4169 &materialize_true,
4170 &materialize_true); 4170 &materialize_true);
4171 __ bind(&materialize_true); 4171 __ bind(&materialize_true);
4172 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 4172 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4173 if (context()->IsAccumulatorValue()) { 4173 if (context()->IsAccumulatorValue()) {
4174 __ mov(eax, isolate()->factory()->true_value()); 4174 __ mov(eax, isolate()->factory()->true_value());
4175 } else { 4175 } else {
(...skipping 22 matching lines...) Expand all
4198 break; 4198 break;
4199 } 4199 }
4200 4200
4201 default: 4201 default:
4202 UNREACHABLE(); 4202 UNREACHABLE();
4203 } 4203 }
4204 } 4204 }
4205 4205
4206 4206
4207 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 4207 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4208 ASSERT(expr->expression()->IsValidReferenceExpression()); 4208 DCHECK(expr->expression()->IsValidReferenceExpression());
4209 4209
4210 Comment cmnt(masm_, "[ CountOperation"); 4210 Comment cmnt(masm_, "[ CountOperation");
4211 SetSourcePosition(expr->position()); 4211 SetSourcePosition(expr->position());
4212 4212
4213 // Expression can only be a property, a global or a (parameter or local) 4213 // Expression can only be a property, a global or a (parameter or local)
4214 // slot. 4214 // slot.
4215 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 4215 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4216 LhsKind assign_type = VARIABLE; 4216 LhsKind assign_type = VARIABLE;
4217 Property* prop = expr->expression()->AsProperty(); 4217 Property* prop = expr->expression()->AsProperty();
4218 // In case of a property we use the uninitialized expression context 4218 // In case of a property we use the uninitialized expression context
4219 // of the key to detect a named property. 4219 // of the key to detect a named property.
4220 if (prop != NULL) { 4220 if (prop != NULL) {
4221 assign_type = 4221 assign_type =
4222 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 4222 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4223 } 4223 }
4224 4224
4225 // Evaluate expression and get value. 4225 // Evaluate expression and get value.
4226 if (assign_type == VARIABLE) { 4226 if (assign_type == VARIABLE) {
4227 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 4227 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
4228 AccumulatorValueContext context(this); 4228 AccumulatorValueContext context(this);
4229 EmitVariableLoad(expr->expression()->AsVariableProxy()); 4229 EmitVariableLoad(expr->expression()->AsVariableProxy());
4230 } else { 4230 } else {
4231 // Reserve space for result of postfix operation. 4231 // Reserve space for result of postfix operation.
4232 if (expr->is_postfix() && !context()->IsEffect()) { 4232 if (expr->is_postfix() && !context()->IsEffect()) {
4233 __ push(Immediate(Smi::FromInt(0))); 4233 __ push(Immediate(Smi::FromInt(0)));
4234 } 4234 }
4235 if (assign_type == NAMED_PROPERTY) { 4235 if (assign_type == NAMED_PROPERTY) {
4236 // Put the object both on the stack and in the register. 4236 // Put the object both on the stack and in the register.
4237 VisitForStackValue(prop->obj()); 4237 VisitForStackValue(prop->obj());
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
4387 context()->Plug(eax); 4387 context()->Plug(eax);
4388 } 4388 }
4389 break; 4389 break;
4390 } 4390 }
4391 } 4391 }
4392 } 4392 }
4393 4393
4394 4394
4395 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4395 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4396 VariableProxy* proxy = expr->AsVariableProxy(); 4396 VariableProxy* proxy = expr->AsVariableProxy();
4397 ASSERT(!context()->IsEffect()); 4397 DCHECK(!context()->IsEffect());
4398 ASSERT(!context()->IsTest()); 4398 DCHECK(!context()->IsTest());
4399 4399
4400 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4400 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4401 Comment cmnt(masm_, "[ Global variable"); 4401 Comment cmnt(masm_, "[ Global variable");
4402 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); 4402 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
4403 __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); 4403 __ mov(LoadIC::NameRegister(), Immediate(proxy->name()));
4404 if (FLAG_vector_ics) { 4404 if (FLAG_vector_ics) {
4405 __ mov(LoadIC::SlotRegister(), 4405 __ mov(LoadIC::SlotRegister(),
4406 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); 4406 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
4407 } 4407 }
4408 // Use a regular load, not a contextual load, to avoid a reference 4408 // Use a regular load, not a contextual load, to avoid a reference
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
4619 return eax; 4619 return eax;
4620 } 4620 }
4621 4621
4622 4622
4623 Register FullCodeGenerator::context_register() { 4623 Register FullCodeGenerator::context_register() {
4624 return esi; 4624 return esi;
4625 } 4625 }
4626 4626
4627 4627
4628 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4628 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4629 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4629 DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4630 __ mov(Operand(ebp, frame_offset), value); 4630 __ mov(Operand(ebp, frame_offset), value);
4631 } 4631 }
4632 4632
4633 4633
4634 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4634 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4635 __ mov(dst, ContextOperand(esi, context_index)); 4635 __ mov(dst, ContextOperand(esi, context_index));
4636 } 4636 }
4637 4637
4638 4638
4639 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4639 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4640 Scope* declaration_scope = scope()->DeclarationScope(); 4640 Scope* declaration_scope = scope()->DeclarationScope();
4641 if (declaration_scope->is_global_scope() || 4641 if (declaration_scope->is_global_scope() ||
4642 declaration_scope->is_module_scope()) { 4642 declaration_scope->is_module_scope()) {
4643 // Contexts nested in the native context have a canonical empty function 4643 // Contexts nested in the native context have a canonical empty function
4644 // as their closure, not the anonymous closure containing the global 4644 // as their closure, not the anonymous closure containing the global
4645 // code. Pass a smi sentinel and let the runtime look up the empty 4645 // code. Pass a smi sentinel and let the runtime look up the empty
4646 // function. 4646 // function.
4647 __ push(Immediate(Smi::FromInt(0))); 4647 __ push(Immediate(Smi::FromInt(0)));
4648 } else if (declaration_scope->is_eval_scope()) { 4648 } else if (declaration_scope->is_eval_scope()) {
4649 // Contexts nested inside eval code have the same closure as the context 4649 // Contexts nested inside eval code have the same closure as the context
4650 // calling eval, not the anonymous closure containing the eval code. 4650 // calling eval, not the anonymous closure containing the eval code.
4651 // Fetch it from the context. 4651 // Fetch it from the context.
4652 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); 4652 __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
4653 } else { 4653 } else {
4654 ASSERT(declaration_scope->is_function_scope()); 4654 DCHECK(declaration_scope->is_function_scope());
4655 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4655 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4656 } 4656 }
4657 } 4657 }
4658 4658
4659 4659
4660 // ---------------------------------------------------------------------------- 4660 // ----------------------------------------------------------------------------
4661 // Non-local control flow support. 4661 // Non-local control flow support.
4662 4662
4663 void FullCodeGenerator::EnterFinallyBlock() { 4663 void FullCodeGenerator::EnterFinallyBlock() {
4664 // Cook return address on top of stack (smi encoded Code* delta) 4664 // Cook return address on top of stack (smi encoded Code* delta)
4665 ASSERT(!result_register().is(edx)); 4665 DCHECK(!result_register().is(edx));
4666 __ pop(edx); 4666 __ pop(edx);
4667 __ sub(edx, Immediate(masm_->CodeObject())); 4667 __ sub(edx, Immediate(masm_->CodeObject()));
4668 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4668 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4669 STATIC_ASSERT(kSmiTag == 0); 4669 STATIC_ASSERT(kSmiTag == 0);
4670 __ SmiTag(edx); 4670 __ SmiTag(edx);
4671 __ push(edx); 4671 __ push(edx);
4672 4672
4673 // Store result register while executing finally block. 4673 // Store result register while executing finally block.
4674 __ push(result_register()); 4674 __ push(result_register());
4675 4675
(...skipping 10 matching lines...) Expand all
4686 __ push(edx); 4686 __ push(edx);
4687 4687
4688 ExternalReference pending_message_script = 4688 ExternalReference pending_message_script =
4689 ExternalReference::address_of_pending_message_script(isolate()); 4689 ExternalReference::address_of_pending_message_script(isolate());
4690 __ mov(edx, Operand::StaticVariable(pending_message_script)); 4690 __ mov(edx, Operand::StaticVariable(pending_message_script));
4691 __ push(edx); 4691 __ push(edx);
4692 } 4692 }
4693 4693
4694 4694
4695 void FullCodeGenerator::ExitFinallyBlock() { 4695 void FullCodeGenerator::ExitFinallyBlock() {
4696 ASSERT(!result_register().is(edx)); 4696 DCHECK(!result_register().is(edx));
4697 // Restore pending message from stack. 4697 // Restore pending message from stack.
4698 __ pop(edx); 4698 __ pop(edx);
4699 ExternalReference pending_message_script = 4699 ExternalReference pending_message_script =
4700 ExternalReference::address_of_pending_message_script(isolate()); 4700 ExternalReference::address_of_pending_message_script(isolate());
4701 __ mov(Operand::StaticVariable(pending_message_script), edx); 4701 __ mov(Operand::StaticVariable(pending_message_script), edx);
4702 4702
4703 __ pop(edx); 4703 __ pop(edx);
4704 __ SmiUntag(edx); 4704 __ SmiUntag(edx);
4705 ExternalReference has_pending_message = 4705 ExternalReference has_pending_message =
4706 ExternalReference::address_of_has_pending_message(isolate()); 4706 ExternalReference::address_of_has_pending_message(isolate());
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
4797 unoptimized_code, call_target_address, replacement_code); 4797 unoptimized_code, call_target_address, replacement_code);
4798 } 4798 }
4799 4799
4800 4800
4801 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4801 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4802 Isolate* isolate, 4802 Isolate* isolate,
4803 Code* unoptimized_code, 4803 Code* unoptimized_code,
4804 Address pc) { 4804 Address pc) {
4805 Address call_target_address = pc - kIntSize; 4805 Address call_target_address = pc - kIntSize;
4806 Address jns_instr_address = call_target_address - 3; 4806 Address jns_instr_address = call_target_address - 3;
4807 ASSERT_EQ(kCallInstruction, *(call_target_address - 1)); 4807 DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
4808 4808
4809 if (*jns_instr_address == kJnsInstruction) { 4809 if (*jns_instr_address == kJnsInstruction) {
4810 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); 4810 DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
4811 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), 4811 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
4812 Assembler::target_address_at(call_target_address, 4812 Assembler::target_address_at(call_target_address,
4813 unoptimized_code)); 4813 unoptimized_code));
4814 return INTERRUPT; 4814 return INTERRUPT;
4815 } 4815 }
4816 4816
4817 ASSERT_EQ(kNopByteOne, *jns_instr_address); 4817 DCHECK_EQ(kNopByteOne, *jns_instr_address);
4818 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); 4818 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
4819 4819
4820 if (Assembler::target_address_at(call_target_address, unoptimized_code) == 4820 if (Assembler::target_address_at(call_target_address, unoptimized_code) ==
4821 isolate->builtins()->OnStackReplacement()->entry()) { 4821 isolate->builtins()->OnStackReplacement()->entry()) {
4822 return ON_STACK_REPLACEMENT; 4822 return ON_STACK_REPLACEMENT;
4823 } 4823 }
4824 4824
4825 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4825 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4826 Assembler::target_address_at(call_target_address, 4826 Assembler::target_address_at(call_target_address,
4827 unoptimized_code)); 4827 unoptimized_code));
4828 return OSR_AFTER_STACK_CHECK; 4828 return OSR_AFTER_STACK_CHECK;
4829 } 4829 }
4830 4830
4831 4831
4832 } } // namespace v8::internal 4832 } } // namespace v8::internal
4833 4833
4834 #endif // V8_TARGET_ARCH_IA32 4834 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698