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

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

Powered by Google App Engine
This is Rietveld 408576698