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

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

Issue 975001: Use untagged int32 values in evaluation of side-effect free expressions. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/register-allocator-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 // CodeGenerator implementation 105 // CodeGenerator implementation
106 106
107 CodeGenerator::CodeGenerator(MacroAssembler* masm) 107 CodeGenerator::CodeGenerator(MacroAssembler* masm)
108 : deferred_(8), 108 : deferred_(8),
109 masm_(masm), 109 masm_(masm),
110 info_(NULL), 110 info_(NULL),
111 frame_(NULL), 111 frame_(NULL),
112 allocator_(NULL), 112 allocator_(NULL),
113 state_(NULL), 113 state_(NULL),
114 loop_nesting_(0), 114 loop_nesting_(0),
115 in_safe_int32_mode_(false),
116 safe_int32_mode_enabled_(true),
115 function_return_is_shadowed_(false), 117 function_return_is_shadowed_(false),
116 in_spilled_code_(false) { 118 in_spilled_code_(false) {
117 } 119 }
118 120
119 121
120 // Calling conventions: 122 // Calling conventions:
121 // ebp: caller's frame pointer 123 // ebp: caller's frame pointer
122 // esp: stack pointer 124 // esp: stack pointer
123 // edi: called JS function 125 // edi: called JS function
124 // esi: callee's context 126 // esi: callee's context
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 slow->Branch(not_equal, not_taken); 432 slow->Branch(not_equal, not_taken);
431 __ mov(tmp.reg(), ContextOperand(context, Context::FCONTEXT_INDEX)); 433 __ mov(tmp.reg(), ContextOperand(context, Context::FCONTEXT_INDEX));
432 return ContextOperand(tmp.reg(), slot->index()); 434 return ContextOperand(tmp.reg(), slot->index());
433 } 435 }
434 436
435 437
436 // Emit code to load the value of an expression to the top of the 438 // Emit code to load the value of an expression to the top of the
437 // frame. If the expression is boolean-valued it may be compiled (or 439 // frame. If the expression is boolean-valued it may be compiled (or
438 // partially compiled) into control flow to the control destination. 440 // partially compiled) into control flow to the control destination.
439 // If force_control is true, control flow is forced. 441 // If force_control is true, control flow is forced.
440 void CodeGenerator::LoadCondition(Expression* x, 442 void CodeGenerator::LoadCondition(Expression* expr,
441 ControlDestination* dest, 443 ControlDestination* dest,
442 bool force_control) { 444 bool force_control) {
443 ASSERT(!in_spilled_code()); 445 ASSERT(!in_spilled_code());
444 int original_height = frame_->height(); 446 int original_height = frame_->height();
445 447
446 { CodeGenState new_state(this, dest); 448 { CodeGenState new_state(this, dest);
447 Visit(x); 449 Visit(expr);
448 450
449 // If we hit a stack overflow, we may not have actually visited 451 // If we hit a stack overflow, we may not have actually visited
450 // the expression. In that case, we ensure that we have a 452 // the expression. In that case, we ensure that we have a
451 // valid-looking frame state because we will continue to generate 453 // valid-looking frame state because we will continue to generate
452 // code as we unwind the C++ stack. 454 // code as we unwind the C++ stack.
453 // 455 //
454 // It's possible to have both a stack overflow and a valid frame 456 // It's possible to have both a stack overflow and a valid frame
455 // state (eg, a subexpression overflowed, visiting it returned 457 // state (eg, a subexpression overflowed, visiting it returned
456 // with a dummied frame state, and visiting this expression 458 // with a dummied frame state, and visiting this expression
457 // returned with a normal-looking state). 459 // returned with a normal-looking state).
(...skipping 16 matching lines...) Expand all
474 476
475 void CodeGenerator::LoadAndSpill(Expression* expression) { 477 void CodeGenerator::LoadAndSpill(Expression* expression) {
476 ASSERT(in_spilled_code()); 478 ASSERT(in_spilled_code());
477 set_in_spilled_code(false); 479 set_in_spilled_code(false);
478 Load(expression); 480 Load(expression);
479 frame_->SpillAll(); 481 frame_->SpillAll();
480 set_in_spilled_code(true); 482 set_in_spilled_code(true);
481 } 483 }
482 484
483 485
486 void CodeGenerator::LoadInSafeInt32Mode(Expression* expr,
487 BreakTarget* unsafe_bailout) {
488 set_unsafe_bailout(unsafe_bailout);
489 set_in_safe_int32_mode(true);
490 Load(expr);
491 Result value = frame_->Pop();
492 ASSERT(frame_->HasNoUntaggedInt32Elements());
493 ConvertInt32ResultToNumber(&value);
494 set_in_safe_int32_mode(false);
495 set_unsafe_bailout(NULL);
496 frame_->Push(&value);
497 }
498
499
500 void CodeGenerator::LoadWithSafeInt32ModeDisabled(Expression* expr) {
501 set_safe_int32_mode_enabled(false);
502 Load(expr);
503 set_safe_int32_mode_enabled(true);
504 }
505
506
507 void CodeGenerator::ConvertInt32ResultToNumber(Result* value) {
508 ASSERT(value->is_untagged_int32());
509 if (value->is_register()) {
510 Register val = value->reg();
511 JumpTarget done;
512 __ add(val, Operand(val));
513 done.Branch(no_overflow, value);
514 __ sar(val, 1);
515 // If there was an overflow, bits 30 and 31 of the original number disagree.
516 __ xor_(val, 0x80000000u);
517 if (CpuFeatures::IsSupported(SSE2)) {
518 CpuFeatures::Scope fscope(SSE2);
519 __ cvtsi2sd(xmm0, Operand(val));
520 } else {
521 // Move val to ST[0] in the FPU
522 // Push and pop are safe with respect to the virtual frame because
523 // all synced elements are below the actual stack pointer.
524 __ push(val);
525 __ fild_s(Operand(esp, 0));
526 __ pop(val);
527 }
528 Result scratch = allocator_->Allocate();
529 ASSERT(scratch.is_register());
530 Label allocation_failed;
531 __ AllocateHeapNumber(val, scratch.reg(),
532 no_reg, &allocation_failed);
533 VirtualFrame* clone = new VirtualFrame(frame_);
534 scratch.Unuse();
535 if (CpuFeatures::IsSupported(SSE2)) {
536 CpuFeatures::Scope fscope(SSE2);
537 __ movdbl(FieldOperand(val, HeapNumber::kValueOffset), xmm0);
538 } else {
539 __ fstp_d(FieldOperand(val, HeapNumber::kValueOffset));
540 }
541 done.Jump(value);
542
543 // Establish the virtual frame, cloned from where AllocateHeapNumber
544 // jumped to allocation_failed.
545 RegisterFile empty_regs;
546 SetFrame(clone, &empty_regs);
547 __ bind(&allocation_failed);
548 unsafe_bailout_->Jump();
549
550 done.Bind(value);
551 } else {
552 ASSERT(value->is_constant());
553 }
554 value->set_untagged_int32(false);
555 }
556
557
484 void CodeGenerator::Load(Expression* expr) { 558 void CodeGenerator::Load(Expression* expr) {
485 #ifdef DEBUG 559 #ifdef DEBUG
486 int original_height = frame_->height(); 560 int original_height = frame_->height();
487 #endif 561 #endif
488 ASSERT(!in_spilled_code()); 562 ASSERT(!in_spilled_code());
489 JumpTarget true_target; 563 JumpTarget done;
490 JumpTarget false_target;
491 ControlDestination dest(&true_target, &false_target, true);
492 LoadCondition(expr, &dest, false);
493 564
494 if (dest.false_was_fall_through()) { 565 // If the expression should be a side-effect-free 32-bit int computation,
495 // The false target was just bound. 566 // compile that SafeInt32 path, and a bailout path.
496 JumpTarget loaded; 567 if (!in_safe_int32_mode() &&
497 frame_->Push(Factory::false_value()); 568 safe_int32_mode_enabled() &&
498 // There may be dangling jumps to the true target. 569 expr->side_effect_free() &&
499 if (true_target.is_linked()) { 570 expr->num_bit_ops() > 2 &&
500 loaded.Jump(); 571 CpuFeatures::IsSupported(SSE2)) {
501 true_target.Bind(); 572 BreakTarget unsafe_bailout;
502 frame_->Push(Factory::true_value()); 573 unsafe_bailout.set_expected_height(frame_->height());
503 loaded.Bind(); 574 LoadInSafeInt32Mode(expr, &unsafe_bailout);
575 done.Jump();
576
577 if (unsafe_bailout.is_linked()) {
578 unsafe_bailout.Bind();
579 LoadWithSafeInt32ModeDisabled(expr);
504 } 580 }
581 } else {
582 JumpTarget true_target;
583 JumpTarget false_target;
505 584
506 } else if (dest.is_used()) { 585 ControlDestination dest(&true_target, &false_target, true);
507 // There is true, and possibly false, control flow (with true as 586 LoadCondition(expr, &dest, false);
508 // the fall through). 587
509 JumpTarget loaded; 588 if (dest.false_was_fall_through()) {
510 frame_->Push(Factory::true_value()); 589 // The false target was just bound.
511 if (false_target.is_linked()) { 590 JumpTarget loaded;
512 loaded.Jump();
513 false_target.Bind();
514 frame_->Push(Factory::false_value()); 591 frame_->Push(Factory::false_value());
515 loaded.Bind(); 592 // There may be dangling jumps to the true target.
516 }
517
518 } else {
519 // We have a valid value on top of the frame, but we still may
520 // have dangling jumps to the true and false targets from nested
521 // subexpressions (eg, the left subexpressions of the
522 // short-circuited boolean operators).
523 ASSERT(has_valid_frame());
524 if (true_target.is_linked() || false_target.is_linked()) {
525 JumpTarget loaded;
526 loaded.Jump(); // Don't lose the current TOS.
527 if (true_target.is_linked()) { 593 if (true_target.is_linked()) {
594 loaded.Jump();
528 true_target.Bind(); 595 true_target.Bind();
529 frame_->Push(Factory::true_value()); 596 frame_->Push(Factory::true_value());
530 if (false_target.is_linked()) { 597 loaded.Bind();
531 loaded.Jump();
532 }
533 } 598 }
599
600 } else if (dest.is_used()) {
601 // There is true, and possibly false, control flow (with true as
602 // the fall through).
603 JumpTarget loaded;
604 frame_->Push(Factory::true_value());
534 if (false_target.is_linked()) { 605 if (false_target.is_linked()) {
606 loaded.Jump();
535 false_target.Bind(); 607 false_target.Bind();
536 frame_->Push(Factory::false_value()); 608 frame_->Push(Factory::false_value());
609 loaded.Bind();
537 } 610 }
538 loaded.Bind(); 611
612 } else {
613 // We have a valid value on top of the frame, but we still may
614 // have dangling jumps to the true and false targets from nested
615 // subexpressions (eg, the left subexpressions of the
616 // short-circuited boolean operators).
617 ASSERT(has_valid_frame());
618 if (true_target.is_linked() || false_target.is_linked()) {
619 JumpTarget loaded;
620 loaded.Jump(); // Don't lose the current TOS.
621 if (true_target.is_linked()) {
622 true_target.Bind();
623 frame_->Push(Factory::true_value());
624 if (false_target.is_linked()) {
625 loaded.Jump();
626 }
627 }
628 if (false_target.is_linked()) {
629 false_target.Bind();
630 frame_->Push(Factory::false_value());
631 }
632 loaded.Bind();
633 }
539 } 634 }
540 } 635 }
541 636 done.Bind();
542 ASSERT(has_valid_frame()); 637 ASSERT(has_valid_frame());
543 ASSERT(frame_->height() == original_height + 1); 638 ASSERT(frame_->height() == original_height + 1);
544 } 639 }
545 640
546 641
547 void CodeGenerator::LoadGlobal() { 642 void CodeGenerator::LoadGlobal() {
548 if (in_spilled_code()) { 643 if (in_spilled_code()) {
549 frame_->EmitPush(GlobalObject()); 644 frame_->EmitPush(GlobalObject());
550 } else { 645 } else {
551 Result temp = allocator_->Allocate(); 646 Result temp = allocator_->Allocate();
(...skipping 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after
4305 // object. 4400 // object.
4306 frame()->EmitPush(esi); 4401 frame()->EmitPush(esi);
4307 frame()->EmitPush(Immediate(boilerplate)); 4402 frame()->EmitPush(Immediate(boilerplate));
4308 return frame()->CallRuntime(Runtime::kNewClosure, 2); 4403 return frame()->CallRuntime(Runtime::kNewClosure, 2);
4309 } 4404 }
4310 } 4405 }
4311 4406
4312 4407
4313 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 4408 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
4314 Comment cmnt(masm_, "[ FunctionLiteral"); 4409 Comment cmnt(masm_, "[ FunctionLiteral");
4315 4410 ASSERT(!in_safe_int32_mode());
4316 // Build the function boilerplate and instantiate it. 4411 // Build the function boilerplate and instantiate it.
4317 Handle<JSFunction> boilerplate = 4412 Handle<JSFunction> boilerplate =
4318 Compiler::BuildBoilerplate(node, script(), this); 4413 Compiler::BuildBoilerplate(node, script(), this);
4319 // Check for stack-overflow exception. 4414 // Check for stack-overflow exception.
4320 if (HasStackOverflow()) return; 4415 if (HasStackOverflow()) return;
4321 Result result = InstantiateBoilerplate(boilerplate); 4416 Result result = InstantiateBoilerplate(boilerplate);
4322 frame()->Push(&result); 4417 frame()->Push(&result);
4323 } 4418 }
4324 4419
4325 4420
4326 void CodeGenerator::VisitFunctionBoilerplateLiteral( 4421 void CodeGenerator::VisitFunctionBoilerplateLiteral(
4327 FunctionBoilerplateLiteral* node) { 4422 FunctionBoilerplateLiteral* node) {
4423 ASSERT(!in_safe_int32_mode());
4328 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 4424 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
4329 Result result = InstantiateBoilerplate(node->boilerplate()); 4425 Result result = InstantiateBoilerplate(node->boilerplate());
4330 frame()->Push(&result); 4426 frame()->Push(&result);
4331 } 4427 }
4332 4428
4333 4429
4334 void CodeGenerator::VisitConditional(Conditional* node) { 4430 void CodeGenerator::VisitConditional(Conditional* node) {
4335 Comment cmnt(masm_, "[ Conditional"); 4431 Comment cmnt(masm_, "[ Conditional");
4432 ASSERT(!in_safe_int32_mode());
4336 JumpTarget then; 4433 JumpTarget then;
4337 JumpTarget else_; 4434 JumpTarget else_;
4338 JumpTarget exit; 4435 JumpTarget exit;
4339 ControlDestination dest(&then, &else_, true); 4436 ControlDestination dest(&then, &else_, true);
4340 LoadCondition(node->condition(), &dest, true); 4437 LoadCondition(node->condition(), &dest, true);
4341 4438
4342 if (dest.false_was_fall_through()) { 4439 if (dest.false_was_fall_through()) {
4343 // The else target was bound, so we compile the else part first. 4440 // The else target was bound, so we compile the else part first.
4344 Load(node->else_expression()); 4441 Load(node->else_expression());
4345 4442
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
4496 result = StoreArgumentsObject(false); 4593 result = StoreArgumentsObject(false);
4497 exit.Bind(&result); 4594 exit.Bind(&result);
4498 return result; 4595 return result;
4499 } 4596 }
4500 4597
4501 4598
4502 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 4599 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
4503 Slot* slot, 4600 Slot* slot,
4504 TypeofState typeof_state, 4601 TypeofState typeof_state,
4505 JumpTarget* slow) { 4602 JumpTarget* slow) {
4603 ASSERT(!in_safe_int32_mode());
4506 // Check that no extension objects have been created by calls to 4604 // Check that no extension objects have been created by calls to
4507 // eval from the current scope to the global scope. 4605 // eval from the current scope to the global scope.
4508 Register context = esi; 4606 Register context = esi;
4509 Result tmp = allocator_->Allocate(); 4607 Result tmp = allocator_->Allocate();
4510 ASSERT(tmp.is_valid()); // All non-reserved registers were available. 4608 ASSERT(tmp.is_valid()); // All non-reserved registers were available.
4511 4609
4512 Scope* s = scope(); 4610 Scope* s = scope();
4513 while (s != NULL) { 4611 while (s != NULL) {
4514 if (s->num_heap_slots() > 0) { 4612 if (s->num_heap_slots() > 0) {
4515 if (s->calls_eval()) { 4613 if (s->calls_eval()) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
4664 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg()); 4762 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
4665 // The results start, value, and temp are unused by going out of 4763 // The results start, value, and temp are unused by going out of
4666 // scope. 4764 // scope.
4667 } 4765 }
4668 4766
4669 exit.Bind(); 4767 exit.Bind();
4670 } 4768 }
4671 } 4769 }
4672 4770
4673 4771
4674 void CodeGenerator::VisitSlot(Slot* node) { 4772 void CodeGenerator::VisitSlot(Slot* slot) {
4675 Comment cmnt(masm_, "[ Slot"); 4773 Comment cmnt(masm_, "[ Slot");
4676 Result result = LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); 4774 if (in_safe_int32_mode()) {
4677 frame()->Push(&result); 4775 if ((slot->type() == Slot::LOCAL && !slot->is_arguments())) {
4776 frame()->UntaggedPushLocalAt(slot->index());
4777 } else if (slot->type() == Slot::PARAMETER) {
4778 frame()->UntaggedPushParameterAt(slot->index());
4779 } else {
4780 UNREACHABLE();
4781 }
4782 } else {
4783 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
4784 frame()->Push(&result);
4785 }
4678 } 4786 }
4679 4787
4680 4788
4681 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 4789 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
4682 Comment cmnt(masm_, "[ VariableProxy"); 4790 Comment cmnt(masm_, "[ VariableProxy");
4683 Variable* var = node->var(); 4791 Variable* var = node->var();
4684 Expression* expr = var->rewrite(); 4792 Expression* expr = var->rewrite();
4685 if (expr != NULL) { 4793 if (expr != NULL) {
4686 Visit(expr); 4794 Visit(expr);
4687 } else { 4795 } else {
4688 ASSERT(var->is_global()); 4796 ASSERT(var->is_global());
4797 ASSERT(!in_safe_int32_mode());
4689 Reference ref(this, node); 4798 Reference ref(this, node);
4690 ref.GetValue(); 4799 ref.GetValue();
4691 } 4800 }
4692 } 4801 }
4693 4802
4694 4803
4695 void CodeGenerator::VisitLiteral(Literal* node) { 4804 void CodeGenerator::VisitLiteral(Literal* node) {
4696 Comment cmnt(masm_, "[ Literal"); 4805 Comment cmnt(masm_, "[ Literal");
4697 frame_->Push(node->handle()); 4806 if (in_safe_int32_mode()) {
4807 frame_->PushUntaggedElement(node->handle());
4808 } else {
4809 frame_->Push(node->handle());
4810 }
4698 } 4811 }
4699 4812
4700 4813
4701 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) { 4814 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
4702 ASSERT(value->IsSmi()); 4815 ASSERT(value->IsSmi());
4703 int bits = reinterpret_cast<int>(*value); 4816 int bits = reinterpret_cast<int>(*value);
4704 __ push(Immediate(bits & 0x0000FFFF)); 4817 __ push(Immediate(bits & 0x0000FFFF));
4705 __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000)); 4818 __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000));
4706 } 4819 }
4707 4820
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4761 // RegExp pattern (2). 4874 // RegExp pattern (2).
4762 __ push(Immediate(node_->pattern())); 4875 __ push(Immediate(node_->pattern()));
4763 // RegExp flags (3). 4876 // RegExp flags (3).
4764 __ push(Immediate(node_->flags())); 4877 __ push(Immediate(node_->flags()));
4765 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 4878 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
4766 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); 4879 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax);
4767 } 4880 }
4768 4881
4769 4882
4770 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 4883 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
4884 ASSERT(!in_safe_int32_mode());
4771 Comment cmnt(masm_, "[ RegExp Literal"); 4885 Comment cmnt(masm_, "[ RegExp Literal");
4772 4886
4773 // Retrieve the literals array and check the allocated entry. Begin 4887 // Retrieve the literals array and check the allocated entry. Begin
4774 // with a writable copy of the function of this activation in a 4888 // with a writable copy of the function of this activation in a
4775 // register. 4889 // register.
4776 frame_->PushFunction(); 4890 frame_->PushFunction();
4777 Result literals = frame_->Pop(); 4891 Result literals = frame_->Pop();
4778 literals.ToRegister(); 4892 literals.ToRegister();
4779 frame_->Spill(literals.reg()); 4893 frame_->Spill(literals.reg());
4780 4894
(...skipping 16 matching lines...) Expand all
4797 deferred->Branch(equal); 4911 deferred->Branch(equal);
4798 deferred->BindExit(); 4912 deferred->BindExit();
4799 literals.Unuse(); 4913 literals.Unuse();
4800 4914
4801 // Push the boilerplate object. 4915 // Push the boilerplate object.
4802 frame_->Push(&boilerplate); 4916 frame_->Push(&boilerplate);
4803 } 4917 }
4804 4918
4805 4919
4806 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 4920 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
4921 ASSERT(!in_safe_int32_mode());
4807 Comment cmnt(masm_, "[ ObjectLiteral"); 4922 Comment cmnt(masm_, "[ ObjectLiteral");
4808 4923
4809 // Load a writable copy of the function of this activation in a 4924 // Load a writable copy of the function of this activation in a
4810 // register. 4925 // register.
4811 frame_->PushFunction(); 4926 frame_->PushFunction();
4812 Result literals = frame_->Pop(); 4927 Result literals = frame_->Pop();
4813 literals.ToRegister(); 4928 literals.ToRegister();
4814 frame_->Spill(literals.reg()); 4929 frame_->Spill(literals.reg());
4815 4930
4816 // Load the literals array of the function. 4931 // Load the literals array of the function.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
4881 // Ignore the result. 4996 // Ignore the result.
4882 break; 4997 break;
4883 } 4998 }
4884 default: UNREACHABLE(); 4999 default: UNREACHABLE();
4885 } 5000 }
4886 } 5001 }
4887 } 5002 }
4888 5003
4889 5004
4890 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 5005 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
5006 ASSERT(!in_safe_int32_mode());
4891 Comment cmnt(masm_, "[ ArrayLiteral"); 5007 Comment cmnt(masm_, "[ ArrayLiteral");
4892 5008
4893 // Load a writable copy of the function of this activation in a 5009 // Load a writable copy of the function of this activation in a
4894 // register. 5010 // register.
4895 frame_->PushFunction(); 5011 frame_->PushFunction();
4896 Result literals = frame_->Pop(); 5012 Result literals = frame_->Pop();
4897 literals.ToRegister(); 5013 literals.ToRegister();
4898 frame_->Spill(literals.reg()); 5014 frame_->Spill(literals.reg());
4899 5015
4900 // Load the literals array of the function. 5016 // Load the literals array of the function.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4952 // Update the write barrier for the array address. 5068 // Update the write barrier for the array address.
4953 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier. 5069 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
4954 Result scratch = allocator_->Allocate(); 5070 Result scratch = allocator_->Allocate();
4955 ASSERT(scratch.is_valid()); 5071 ASSERT(scratch.is_valid());
4956 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg()); 5072 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
4957 } 5073 }
4958 } 5074 }
4959 5075
4960 5076
4961 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { 5077 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
5078 ASSERT(!in_safe_int32_mode());
4962 ASSERT(!in_spilled_code()); 5079 ASSERT(!in_spilled_code());
4963 // Call runtime routine to allocate the catch extension object and 5080 // Call runtime routine to allocate the catch extension object and
4964 // assign the exception value to the catch variable. 5081 // assign the exception value to the catch variable.
4965 Comment cmnt(masm_, "[ CatchExtensionObject"); 5082 Comment cmnt(masm_, "[ CatchExtensionObject");
4966 Load(node->key()); 5083 Load(node->key());
4967 Load(node->value()); 5084 Load(node->value());
4968 Result result = 5085 Result result =
4969 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 5086 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
4970 frame_->Push(&result); 5087 frame_->Push(&result);
4971 } 5088 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
5171 frame()->Push(&result); 5288 frame()->Push(&result);
5172 frame()->Push(&receiver); 5289 frame()->Push(&receiver);
5173 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 5290 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5174 } 5291 }
5175 5292
5176 ASSERT(frame()->height() == original_height + 1); 5293 ASSERT(frame()->height() == original_height + 1);
5177 } 5294 }
5178 5295
5179 5296
5180 void CodeGenerator::VisitAssignment(Assignment* node) { 5297 void CodeGenerator::VisitAssignment(Assignment* node) {
5298 ASSERT(!in_safe_int32_mode());
5181 #ifdef DEBUG 5299 #ifdef DEBUG
5182 int original_height = frame()->height(); 5300 int original_height = frame()->height();
5183 #endif 5301 #endif
5184 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 5302 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5185 Property* prop = node->target()->AsProperty(); 5303 Property* prop = node->target()->AsProperty();
5186 5304
5187 if (var != NULL && !var->is_global()) { 5305 if (var != NULL && !var->is_global()) {
5188 EmitSlotAssignment(node); 5306 EmitSlotAssignment(node);
5189 5307
5190 } else if ((prop != NULL && prop->key()->IsPropertyName()) || 5308 } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
(...skipping 15 matching lines...) Expand all
5206 // The runtime call doesn't actually return but the code generator will 5324 // The runtime call doesn't actually return but the code generator will
5207 // still generate code and expects a certain frame height. 5325 // still generate code and expects a certain frame height.
5208 frame()->Push(&result); 5326 frame()->Push(&result);
5209 } 5327 }
5210 5328
5211 ASSERT(frame()->height() == original_height + 1); 5329 ASSERT(frame()->height() == original_height + 1);
5212 } 5330 }
5213 5331
5214 5332
5215 void CodeGenerator::VisitThrow(Throw* node) { 5333 void CodeGenerator::VisitThrow(Throw* node) {
5334 ASSERT(!in_safe_int32_mode());
5216 Comment cmnt(masm_, "[ Throw"); 5335 Comment cmnt(masm_, "[ Throw");
5217 Load(node->exception()); 5336 Load(node->exception());
5218 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 5337 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
5219 frame_->Push(&result); 5338 frame_->Push(&result);
5220 } 5339 }
5221 5340
5222 5341
5223 void CodeGenerator::VisitProperty(Property* node) { 5342 void CodeGenerator::VisitProperty(Property* node) {
5343 ASSERT(!in_safe_int32_mode());
5224 Comment cmnt(masm_, "[ Property"); 5344 Comment cmnt(masm_, "[ Property");
5225 Reference property(this, node); 5345 Reference property(this, node);
5226 property.GetValue(); 5346 property.GetValue();
5227 } 5347 }
5228 5348
5229 5349
5230 void CodeGenerator::VisitCall(Call* node) { 5350 void CodeGenerator::VisitCall(Call* node) {
5351 ASSERT(!in_safe_int32_mode());
5231 Comment cmnt(masm_, "[ Call"); 5352 Comment cmnt(masm_, "[ Call");
5232 5353
5233 Expression* function = node->expression(); 5354 Expression* function = node->expression();
5234 ZoneList<Expression*>* args = node->arguments(); 5355 ZoneList<Expression*>* args = node->arguments();
5235 5356
5236 // Check if the function is a variable or a property. 5357 // Check if the function is a variable or a property.
5237 Variable* var = function->AsVariableProxy()->AsVariable(); 5358 Variable* var = function->AsVariableProxy()->AsVariable();
5238 Property* property = function->AsProperty(); 5359 Property* property = function->AsProperty();
5239 5360
5240 // ------------------------------------------------------------------------ 5361 // ------------------------------------------------------------------------
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
5436 // Pass the global proxy as the receiver. 5557 // Pass the global proxy as the receiver.
5437 LoadGlobalReceiver(); 5558 LoadGlobalReceiver();
5438 5559
5439 // Call the function. 5560 // Call the function.
5440 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); 5561 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
5441 } 5562 }
5442 } 5563 }
5443 5564
5444 5565
5445 void CodeGenerator::VisitCallNew(CallNew* node) { 5566 void CodeGenerator::VisitCallNew(CallNew* node) {
5567 ASSERT(!in_safe_int32_mode());
5446 Comment cmnt(masm_, "[ CallNew"); 5568 Comment cmnt(masm_, "[ CallNew");
5447 5569
5448 // According to ECMA-262, section 11.2.2, page 44, the function 5570 // According to ECMA-262, section 11.2.2, page 44, the function
5449 // expression in new calls must be evaluated before the 5571 // expression in new calls must be evaluated before the
5450 // arguments. This is different from ordinary calls, where the 5572 // arguments. This is different from ordinary calls, where the
5451 // actual function to call is resolved after the arguments have been 5573 // actual function to call is resolved after the arguments have been
5452 // evaluated. 5574 // evaluated.
5453 5575
5454 // Compute function to call and use the global object as the 5576 // Compute function to call and use the global object as the
5455 // receiver. There is no need to use the global proxy here because 5577 // receiver. There is no need to use the global proxy here because
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after
6363 __ bind(&runtime); 6485 __ bind(&runtime);
6364 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1); 6486 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1);
6365 6487
6366 end.Bind(&result); 6488 end.Bind(&result);
6367 frame()->Push(&result); 6489 frame()->Push(&result);
6368 } 6490 }
6369 } 6491 }
6370 6492
6371 6493
6372 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 6494 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
6495 ASSERT(!in_safe_int32_mode());
6373 if (CheckForInlineRuntimeCall(node)) { 6496 if (CheckForInlineRuntimeCall(node)) {
6374 return; 6497 return;
6375 } 6498 }
6376 6499
6377 ZoneList<Expression*>* args = node->arguments(); 6500 ZoneList<Expression*>* args = node->arguments();
6378 Comment cmnt(masm_, "[ CallRuntime"); 6501 Comment cmnt(masm_, "[ CallRuntime");
6379 Runtime::Function* function = node->function(); 6502 Runtime::Function* function = node->function();
6380 6503
6381 if (function == NULL) { 6504 if (function == NULL) {
6382 // Push the builtins object found in the current global object. 6505 // Push the builtins object found in the current global object.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
6489 expression->AsLiteral()->IsNull())) { 6612 expression->AsLiteral()->IsNull())) {
6490 // Omit evaluating the value of the primitive literal. 6613 // Omit evaluating the value of the primitive literal.
6491 // It will be discarded anyway, and can have no side effect. 6614 // It will be discarded anyway, and can have no side effect.
6492 frame_->Push(Factory::undefined_value()); 6615 frame_->Push(Factory::undefined_value());
6493 } else { 6616 } else {
6494 Load(node->expression()); 6617 Load(node->expression());
6495 frame_->SetElementAt(0, Factory::undefined_value()); 6618 frame_->SetElementAt(0, Factory::undefined_value());
6496 } 6619 }
6497 6620
6498 } else { 6621 } else {
6499 Load(node->expression()); 6622 if (in_safe_int32_mode()) {
6500 bool overwrite = 6623 Visit(node->expression());
6501 (node->expression()->AsBinaryOperation() != NULL && 6624 Result value = frame_->Pop();
6502 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 6625 ASSERT(value.is_untagged_int32());
6503 switch (op) { 6626 // Registers containing an int32 value are not multiply used.
6504 case Token::SUB: { 6627 ASSERT(!value.is_register() || !frame_->is_used(value.reg()));
6505 GenericUnaryOpStub stub(Token::SUB, overwrite); 6628 value.ToRegister();
6506 Result operand = frame_->Pop(); 6629 switch (op) {
6507 Result answer = frame_->CallStub(&stub, &operand); 6630 case Token::SUB: {
6508 frame_->Push(&answer); 6631 __ neg(value.reg());
6509 break; 6632 if (node->no_negative_zero()) {
6633 // -MIN_INT is MIN_INT with the overflow flag set.
6634 unsafe_bailout_->Branch(overflow);
6635 } else {
6636 // MIN_INT and 0 both have bad negations. They both have 31 zeros.
6637 __ test(value.reg(), Immediate(0x7FFFFFFF));
6638 unsafe_bailout_->Branch(zero);
6639 }
6640 break;
6641 }
6642 case Token::BIT_NOT: {
6643 __ not_(value.reg());
6644 break;
6645 }
6646 case Token::ADD: {
6647 // Unary plus has no effect on int32 values.
6648 break;
6649 }
6650 default:
6651 UNREACHABLE();
6652 break;
6510 } 6653 }
6654 frame_->Push(&value);
6511 6655
6512 case Token::BIT_NOT: { 6656 } else {
6513 // Smi check. 6657 Load(node->expression());
6514 JumpTarget smi_label; 6658 bool overwrite =
6515 JumpTarget continue_label; 6659 (node->expression()->AsBinaryOperation() != NULL &&
6516 Result operand = frame_->Pop(); 6660 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
6517 operand.ToRegister(); 6661 switch (op) {
6518 __ test(operand.reg(), Immediate(kSmiTagMask)); 6662 case Token::SUB: {
6519 smi_label.Branch(zero, &operand, taken); 6663 GenericUnaryOpStub stub(Token::SUB, overwrite);
6664 Result operand = frame_->Pop();
6665 Result answer = frame_->CallStub(&stub, &operand);
6666 frame_->Push(&answer);
6667 break;
6668 }
6520 6669
6521 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 6670 case Token::BIT_NOT: {
6522 Result answer = frame_->CallStub(&stub, &operand); 6671 // Smi check.
6523 continue_label.Jump(&answer); 6672 JumpTarget smi_label;
6673 JumpTarget continue_label;
6674 Result operand = frame_->Pop();
6675 operand.ToRegister();
6676 __ test(operand.reg(), Immediate(kSmiTagMask));
6677 smi_label.Branch(zero, &operand, taken);
6524 6678
6525 smi_label.Bind(&answer); 6679 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
6526 answer.ToRegister(); 6680 Result answer = frame_->CallStub(&stub, &operand);
6527 frame_->Spill(answer.reg()); 6681 continue_label.Jump(&answer);
6528 __ not_(answer.reg());
6529 __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag.
6530 6682
6531 continue_label.Bind(&answer); 6683 smi_label.Bind(&answer);
6532 frame_->Push(&answer); 6684 answer.ToRegister();
6533 break; 6685 frame_->Spill(answer.reg());
6534 } 6686 __ not_(answer.reg());
6687 __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag.
6535 6688
6536 case Token::ADD: { 6689 continue_label.Bind(&answer);
6537 // Smi check. 6690 frame_->Push(&answer);
6538 JumpTarget continue_label; 6691 break;
6539 Result operand = frame_->Pop(); 6692 }
6540 operand.ToRegister();
6541 __ test(operand.reg(), Immediate(kSmiTagMask));
6542 continue_label.Branch(zero, &operand, taken);
6543 6693
6544 frame_->Push(&operand); 6694 case Token::ADD: {
6545 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, 6695 // Smi check.
6696 JumpTarget continue_label;
6697 Result operand = frame_->Pop();
6698 operand.ToRegister();
6699 __ test(operand.reg(), Immediate(kSmiTagMask));
6700 continue_label.Branch(zero, &operand, taken);
6701
6702 frame_->Push(&operand);
6703 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER,
6546 CALL_FUNCTION, 1); 6704 CALL_FUNCTION, 1);
6547 6705
6548 continue_label.Bind(&answer); 6706 continue_label.Bind(&answer);
6549 frame_->Push(&answer); 6707 frame_->Push(&answer);
6550 break; 6708 break;
6709 }
6710
6711 default:
6712 // NOT, DELETE, TYPEOF, and VOID are handled outside the
6713 // switch.
6714 UNREACHABLE();
6551 } 6715 }
6552
6553 default:
6554 // NOT, DELETE, TYPEOF, and VOID are handled outside the
6555 // switch.
6556 UNREACHABLE();
6557 } 6716 }
6558 } 6717 }
6559 } 6718 }
6560 6719
6561 6720
6562 // The value in dst was optimistically incremented or decremented. The 6721 // The value in dst was optimistically incremented or decremented. The
6563 // result overflowed or was not smi tagged. Undo the operation, call 6722 // result overflowed or was not smi tagged. Undo the operation, call
6564 // into the runtime to convert the argument to a number, and call the 6723 // into the runtime to convert the argument to a number, and call the
6565 // specialized add or subtract stub. The result is left in dst. 6724 // specialized add or subtract stub. The result is left in dst.
6566 class DeferredPrefixCountOperation: public DeferredCode { 6725 class DeferredPrefixCountOperation: public DeferredCode {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
6639 __ CallRuntime(Runtime::kNumberAdd, 2); 6798 __ CallRuntime(Runtime::kNumberAdd, 2);
6640 } else { 6799 } else {
6641 __ CallRuntime(Runtime::kNumberSub, 2); 6800 __ CallRuntime(Runtime::kNumberSub, 2);
6642 } 6801 }
6643 if (!dst_.is(eax)) __ mov(dst_, eax); 6802 if (!dst_.is(eax)) __ mov(dst_, eax);
6644 __ pop(old_); 6803 __ pop(old_);
6645 } 6804 }
6646 6805
6647 6806
6648 void CodeGenerator::VisitCountOperation(CountOperation* node) { 6807 void CodeGenerator::VisitCountOperation(CountOperation* node) {
6808 ASSERT(!in_safe_int32_mode());
6649 Comment cmnt(masm_, "[ CountOperation"); 6809 Comment cmnt(masm_, "[ CountOperation");
6650 6810
6651 bool is_postfix = node->is_postfix(); 6811 bool is_postfix = node->is_postfix();
6652 bool is_increment = node->op() == Token::INC; 6812 bool is_increment = node->op() == Token::INC;
6653 6813
6654 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 6814 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
6655 bool is_const = (var != NULL && var->mode() == Variable::CONST); 6815 bool is_const = (var != NULL && var->mode() == Variable::CONST);
6656 6816
6657 // Postfix operations need a stack slot under the reference to hold 6817 // Postfix operations need a stack slot under the reference to hold
6658 // the old value while the new value is being stored. This is so that 6818 // the old value while the new value is being stored. This is so that
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
6752 frame_->Push(&new_value); 6912 frame_->Push(&new_value);
6753 // Non-constant: update the reference. 6913 // Non-constant: update the reference.
6754 if (!is_const) target.SetValue(NOT_CONST_INIT); 6914 if (!is_const) target.SetValue(NOT_CONST_INIT);
6755 } 6915 }
6756 6916
6757 // Postfix: drop the new value and use the old. 6917 // Postfix: drop the new value and use the old.
6758 if (is_postfix) frame_->Drop(); 6918 if (is_postfix) frame_->Drop();
6759 } 6919 }
6760 6920
6761 6921
6922 void CodeGenerator::Int32BinaryOperation(BinaryOperation* node) {
6923 Token::Value op = node->op();
6924 Comment cmnt(masm_, "[ Int32BinaryOperation");
6925 ASSERT(in_safe_int32_mode());
6926 ASSERT(safe_int32_mode_enabled());
6927 ASSERT(FLAG_safe_int32_compiler);
6928
6929 if (op == Token::COMMA) {
6930 // Discard left value.
6931 frame_->Nip(1);
6932 return;
6933 }
6934
6935 Result right = frame_->Pop();
6936 Result left = frame_->Pop();
6937
6938 ASSERT(right.is_untagged_int32());
6939 ASSERT(left.is_untagged_int32());
6940 // Registers containing an int32 value are not multiply used.
6941 ASSERT(!left.is_register() || !frame_->is_used(left.reg()));
6942 ASSERT(!right.is_register() || !frame_->is_used(right.reg()));
6943
6944 switch (op) {
6945 case Token::COMMA:
6946 case Token::OR:
6947 case Token::AND:
6948 UNREACHABLE();
6949 break;
6950 case Token::BIT_OR:
6951 case Token::BIT_XOR:
6952 case Token::BIT_AND:
6953 left.ToRegister();
6954 right.ToRegister();
6955 if (op == Token::BIT_OR) {
6956 __ or_(left.reg(), Operand(right.reg()));
6957 } else if (op == Token::BIT_XOR) {
6958 __ xor_(left.reg(), Operand(right.reg()));
6959 } else {
6960 ASSERT(op == Token::BIT_AND);
6961 __ and_(left.reg(), Operand(right.reg()));
6962 }
6963 frame_->Push(&left);
6964 right.Unuse();
6965 break;
6966 case Token::SAR:
6967 case Token::SHL:
6968 case Token::SHR: {
6969 bool test_shr_overflow = false;
6970 left.ToRegister();
6971 if (right.is_constant()) {
6972 ASSERT(right.handle()->IsSmi() || right.handle()->IsHeapNumber());
6973 int shift_amount = NumberToInt32(*right.handle()) & 0x1F;
6974 if (op == Token::SAR) {
6975 __ sar(left.reg(), shift_amount);
6976 } else if (op == Token::SHL) {
6977 __ shl(left.reg(), shift_amount);
6978 } else {
6979 ASSERT(op == Token::SHR);
6980 __ shr(left.reg(), shift_amount);
6981 if (shift_amount == 0) test_shr_overflow = true;
6982 }
6983 } else {
6984 // Move right to ecx
6985 if (left.is_register() && left.reg().is(ecx)) {
6986 right.ToRegister();
6987 __ xchg(left.reg(), right.reg());
6988 left = right; // Left is unused here, copy of right unused by Push.
6989 } else {
6990 right.ToRegister(ecx);
6991 left.ToRegister();
6992 }
6993 if (op == Token::SAR) {
6994 __ sar_cl(left.reg());
6995 } else if (op == Token::SHL) {
6996 __ shl_cl(left.reg());
6997 } else {
6998 ASSERT(op == Token::SHR);
6999 __ shr_cl(left.reg());
7000 test_shr_overflow = true;
7001 }
7002 }
7003 {
7004 Register left_reg = left.reg();
7005 frame_->Push(&left);
7006 right.Unuse();
7007 if (test_shr_overflow && !node->to_int32()) {
7008 // Uint32 results with top bit set are not Int32 values.
7009 // If they will be forced to Int32, skip the test.
7010 // Test is needed because shr with shift amount 0 does not set flags.
7011 __ test(left_reg, Operand(left_reg));
7012 unsafe_bailout_->Branch(sign);
7013 }
7014 }
7015 break;
7016 }
7017 case Token::ADD:
7018 case Token::SUB:
7019 case Token::MUL:
7020 left.ToRegister();
7021 right.ToRegister();
7022 if (op == Token::ADD) {
7023 __ add(left.reg(), Operand(right.reg()));
7024 } else if (op == Token::SUB) {
7025 __ sub(left.reg(), Operand(right.reg()));
7026 } else {
7027 ASSERT(op == Token::MUL);
7028 // We have statically verified that a negative zero can be ignored.
7029 __ imul(left.reg(), Operand(right.reg()));
7030 }
7031 right.Unuse();
7032 frame_->Push(&left);
7033 if (!node->to_int32()) {
7034 // If ToInt32 is called on the result of ADD, SUB, or MUL, we don't
7035 // care about overflows.
7036 unsafe_bailout_->Branch(overflow);
7037 }
7038 break;
7039 case Token::DIV:
7040 case Token::MOD: {
7041 if (right.is_register() && (right.reg().is(eax) || right.reg().is(edx))) {
7042 if (left.is_register() && left.reg().is(edi)) {
7043 right.ToRegister(ebx);
7044 } else {
7045 right.ToRegister(edi);
7046 }
7047 }
7048 left.ToRegister(eax);
7049 Result edx_reg = allocator_->Allocate(edx);
7050 right.ToRegister();
7051 // The results are unused here because BreakTarget::Branch cannot handle
7052 // live results.
7053 Register right_reg = right.reg();
7054 left.Unuse();
7055 right.Unuse();
7056 edx_reg.Unuse();
7057 __ cmp(right_reg, 0);
7058 // Ensure divisor is positive: no chance of non-int32 or -0 result.
7059 unsafe_bailout_->Branch(less_equal);
7060 __ cdq(); // Sign-extend eax into edx:eax
7061 __ idiv(right_reg);
7062 if (op == Token::MOD) {
7063 Result edx_result(edx, NumberInfo::Integer32());
7064 edx_result.set_untagged_int32(true);
7065 frame_->Push(&edx_result);
7066 } else {
7067 ASSERT(op == Token::DIV);
7068 __ test(edx, Operand(edx));
7069 unsafe_bailout_->Branch(not_equal);
7070 Result eax_result(eax, NumberInfo::Integer32());
7071 eax_result.set_untagged_int32(true);
7072 frame_->Push(&eax_result);
7073 }
7074 break;
7075 }
7076 default:
7077 UNREACHABLE();
7078 break;
7079 }
7080 }
7081
6762 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 7082 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
6763 Comment cmnt(masm_, "[ BinaryOperation"); 7083 Comment cmnt(masm_, "[ BinaryOperation");
6764 Token::Value op = node->op(); 7084 Token::Value op = node->op();
6765 7085
6766 // According to ECMA-262 section 11.11, page 58, the binary logical 7086 // According to ECMA-262 section 11.11, page 58, the binary logical
6767 // operators must yield the result of one of the two expressions 7087 // operators must yield the result of one of the two expressions
6768 // before any ToBoolean() conversions. This means that the value 7088 // before any ToBoolean() conversions. This means that the value
6769 // produced by a && or || operator is not necessarily a boolean. 7089 // produced by a && or || operator is not necessarily a boolean.
6770 7090
6771 // NOTE: If the left hand side produces a materialized value (not 7091 // NOTE: If the left hand side produces a materialized value (not
6772 // control flow), we force the right hand side to do the same. This 7092 // control flow), we force the right hand side to do the same. This
6773 // is necessary because we assume that if we get control flow on the 7093 // is necessary because we assume that if we get control flow on the
6774 // last path out of an expression we got it on all paths. 7094 // last path out of an expression we got it on all paths.
6775 if (op == Token::AND) { 7095 if (op == Token::AND) {
7096 ASSERT(!in_safe_int32_mode());
6776 JumpTarget is_true; 7097 JumpTarget is_true;
6777 ControlDestination dest(&is_true, destination()->false_target(), true); 7098 ControlDestination dest(&is_true, destination()->false_target(), true);
6778 LoadCondition(node->left(), &dest, false); 7099 LoadCondition(node->left(), &dest, false);
6779 7100
6780 if (dest.false_was_fall_through()) { 7101 if (dest.false_was_fall_through()) {
6781 // The current false target was used as the fall-through. If 7102 // The current false target was used as the fall-through. If
6782 // there are no dangling jumps to is_true then the left 7103 // there are no dangling jumps to is_true then the left
6783 // subexpression was unconditionally false. Otherwise we have 7104 // subexpression was unconditionally false. Otherwise we have
6784 // paths where we do have to evaluate the right subexpression. 7105 // paths where we do have to evaluate the right subexpression.
6785 if (is_true.is_linked()) { 7106 if (is_true.is_linked()) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6829 7150
6830 // Compile right side expression. 7151 // Compile right side expression.
6831 is_true.Bind(); 7152 is_true.Bind();
6832 Load(node->right()); 7153 Load(node->right());
6833 7154
6834 // Exit (always with a materialized value). 7155 // Exit (always with a materialized value).
6835 exit.Bind(); 7156 exit.Bind();
6836 } 7157 }
6837 7158
6838 } else if (op == Token::OR) { 7159 } else if (op == Token::OR) {
7160 ASSERT(!in_safe_int32_mode());
6839 JumpTarget is_false; 7161 JumpTarget is_false;
6840 ControlDestination dest(destination()->true_target(), &is_false, false); 7162 ControlDestination dest(destination()->true_target(), &is_false, false);
6841 LoadCondition(node->left(), &dest, false); 7163 LoadCondition(node->left(), &dest, false);
6842 7164
6843 if (dest.true_was_fall_through()) { 7165 if (dest.true_was_fall_through()) {
6844 // The current true target was used as the fall-through. If 7166 // The current true target was used as the fall-through. If
6845 // there are no dangling jumps to is_false then the left 7167 // there are no dangling jumps to is_false then the left
6846 // subexpression was unconditionally true. Otherwise we have 7168 // subexpression was unconditionally true. Otherwise we have
6847 // paths where we do have to evaluate the right subexpression. 7169 // paths where we do have to evaluate the right subexpression.
6848 if (is_false.is_linked()) { 7170 if (is_false.is_linked()) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
6890 frame_->Drop(); 7212 frame_->Drop();
6891 7213
6892 // Compile right side expression. 7214 // Compile right side expression.
6893 is_false.Bind(); 7215 is_false.Bind();
6894 Load(node->right()); 7216 Load(node->right());
6895 7217
6896 // Exit (always with a materialized value). 7218 // Exit (always with a materialized value).
6897 exit.Bind(); 7219 exit.Bind();
6898 } 7220 }
6899 7221
7222 } else if (in_safe_int32_mode()) {
7223 Visit(node->left());
7224 Visit(node->right());
7225 Int32BinaryOperation(node);
6900 } else { 7226 } else {
6901 // NOTE: The code below assumes that the slow cases (calls to runtime) 7227 // NOTE: The code below assumes that the slow cases (calls to runtime)
6902 // never return a constant/immutable object. 7228 // never return a constant/immutable object.
6903 OverwriteMode overwrite_mode = NO_OVERWRITE; 7229 OverwriteMode overwrite_mode = NO_OVERWRITE;
6904 if (node->left()->AsBinaryOperation() != NULL && 7230 if (node->left()->AsBinaryOperation() != NULL &&
6905 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) { 7231 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
6906 overwrite_mode = OVERWRITE_LEFT; 7232 overwrite_mode = OVERWRITE_LEFT;
6907 } else if (node->right()->AsBinaryOperation() != NULL && 7233 } else if (node->right()->AsBinaryOperation() != NULL &&
6908 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) { 7234 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
6909 overwrite_mode = OVERWRITE_RIGHT; 7235 overwrite_mode = OVERWRITE_RIGHT;
6910 } 7236 }
6911 7237
6912 if (node->left()->IsTrivial()) { 7238 if (node->left()->IsTrivial()) {
6913 Load(node->right()); 7239 Load(node->right());
6914 Result right = frame_->Pop(); 7240 Result right = frame_->Pop();
6915 frame_->Push(node->left()); 7241 frame_->Push(node->left());
6916 frame_->Push(&right); 7242 frame_->Push(&right);
6917 } else { 7243 } else {
6918 Load(node->left()); 7244 Load(node->left());
6919 Load(node->right()); 7245 Load(node->right());
6920 } 7246 }
6921 GenericBinaryOperation(node->op(), node->type(), 7247 GenericBinaryOperation(node->op(), node->type(),
6922 overwrite_mode, node->no_negative_zero()); 7248 overwrite_mode, node->no_negative_zero());
6923 } 7249 }
6924 } 7250 }
6925 7251
6926 7252
6927 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 7253 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
7254 ASSERT(!in_safe_int32_mode());
6928 frame_->PushFunction(); 7255 frame_->PushFunction();
6929 } 7256 }
6930 7257
6931 7258
6932 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 7259 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
7260 ASSERT(!in_safe_int32_mode());
6933 Comment cmnt(masm_, "[ CompareOperation"); 7261 Comment cmnt(masm_, "[ CompareOperation");
6934 7262
6935 bool left_already_loaded = false; 7263 bool left_already_loaded = false;
6936 7264
6937 // Get the expressions from the node. 7265 // Get the expressions from the node.
6938 Expression* left = node->left(); 7266 Expression* left = node->left();
6939 Expression* right = node->right(); 7267 Expression* right = node->right();
6940 Token::Value op = node->op(); 7268 Token::Value op = node->op();
6941 // To make typeof testing for natives implemented in JavaScript really 7269 // To make typeof testing for natives implemented in JavaScript really
6942 // efficient, we generate special code for expressions of the form: 7270 // efficient, we generate special code for expressions of the form:
(...skipping 4922 matching lines...) Expand 10 before | Expand all | Expand 10 after
11865 12193
11866 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12194 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
11867 // tagged as a small integer. 12195 // tagged as a small integer.
11868 __ bind(&runtime); 12196 __ bind(&runtime);
11869 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12197 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
11870 } 12198 }
11871 12199
11872 #undef __ 12200 #undef __
11873 12201
11874 } } // namespace v8::internal 12202 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/register-allocator-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698