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

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

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
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
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;
490 JumpTarget false_target;
491 ControlDestination dest(&true_target, &false_target, true);
492 LoadCondition(expr, &dest, false);
493 563
494 if (dest.false_was_fall_through()) { 564 // If the expression should be a side-effect-free 32-bit int computation,
495 // The false target was just bound. 565 // compile that SafeInt32 path, and a bailout path.
496 JumpTarget loaded; 566 if (!in_safe_int32_mode() &&
497 frame_->Push(Factory::false_value()); 567 safe_int32_mode_enabled() &&
498 // There may be dangling jumps to the true target. 568 expr->side_effect_free() &&
499 if (true_target.is_linked()) { 569 expr->num_bit_ops() > 2 &&
500 loaded.Jump(); 570 CpuFeatures::IsSupported(SSE2)) {
501 true_target.Bind(); 571 BreakTarget unsafe_bailout;
502 frame_->Push(Factory::true_value()); 572 JumpTarget done;
503 loaded.Bind(); 573 unsafe_bailout.set_expected_height(frame_->height());
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 done.Bind();
582 } else {
583 JumpTarget true_target;
584 JumpTarget false_target;
505 585
506 } else if (dest.is_used()) { 586 ControlDestination dest(&true_target, &false_target, true);
507 // There is true, and possibly false, control flow (with true as 587 LoadCondition(expr, &dest, false);
508 // the fall through). 588
509 JumpTarget loaded; 589 if (dest.false_was_fall_through()) {
510 frame_->Push(Factory::true_value()); 590 // The false target was just bound.
511 if (false_target.is_linked()) { 591 JumpTarget loaded;
512 loaded.Jump();
513 false_target.Bind();
514 frame_->Push(Factory::false_value()); 592 frame_->Push(Factory::false_value());
515 loaded.Bind(); 593 // 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()) { 594 if (true_target.is_linked()) {
595 loaded.Jump();
528 true_target.Bind(); 596 true_target.Bind();
529 frame_->Push(Factory::true_value()); 597 frame_->Push(Factory::true_value());
530 if (false_target.is_linked()) { 598 loaded.Bind();
531 loaded.Jump();
532 }
533 } 599 }
600
601 } else if (dest.is_used()) {
602 // There is true, and possibly false, control flow (with true as
603 // the fall through).
604 JumpTarget loaded;
605 frame_->Push(Factory::true_value());
534 if (false_target.is_linked()) { 606 if (false_target.is_linked()) {
607 loaded.Jump();
535 false_target.Bind(); 608 false_target.Bind();
536 frame_->Push(Factory::false_value()); 609 frame_->Push(Factory::false_value());
610 loaded.Bind();
537 } 611 }
538 loaded.Bind(); 612
613 } else {
614 // We have a valid value on top of the frame, but we still may
615 // have dangling jumps to the true and false targets from nested
616 // subexpressions (eg, the left subexpressions of the
617 // short-circuited boolean operators).
618 ASSERT(has_valid_frame());
619 if (true_target.is_linked() || false_target.is_linked()) {
620 JumpTarget loaded;
621 loaded.Jump(); // Don't lose the current TOS.
622 if (true_target.is_linked()) {
623 true_target.Bind();
624 frame_->Push(Factory::true_value());
625 if (false_target.is_linked()) {
626 loaded.Jump();
627 }
628 }
629 if (false_target.is_linked()) {
630 false_target.Bind();
631 frame_->Push(Factory::false_value());
632 }
633 loaded.Bind();
634 }
539 } 635 }
540 } 636 }
541
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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 Comment cmnt(masm_, "[ ToBoolean"); 825 Comment cmnt(masm_, "[ ToBoolean");
731 826
732 // The value to convert should be popped from the frame. 827 // The value to convert should be popped from the frame.
733 Result value = frame_->Pop(); 828 Result value = frame_->Pop();
734 value.ToRegister(); 829 value.ToRegister();
735 830
736 if (value.is_integer32()) { // Also takes Smi case. 831 if (value.is_integer32()) { // Also takes Smi case.
737 Comment cmnt(masm_, "ONLY_INTEGER_32"); 832 Comment cmnt(masm_, "ONLY_INTEGER_32");
738 if (FLAG_debug_code) { 833 if (FLAG_debug_code) {
739 Label ok; 834 Label ok;
740 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); 835 __ AbortIfNotNumber(value.reg());
741 __ test(value.reg(), Immediate(kSmiTagMask)); 836 __ test(value.reg(), Immediate(kSmiTagMask));
742 __ j(zero, &ok); 837 __ j(zero, &ok);
743 __ fldz(); 838 __ fldz();
744 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); 839 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
745 __ FCmp(); 840 __ FCmp();
746 __ j(not_zero, &ok); 841 __ j(not_zero, &ok);
747 __ Abort("Smi was wrapped in HeapNumber in output from bitop"); 842 __ Abort("Smi was wrapped in HeapNumber in output from bitop");
748 __ bind(&ok); 843 __ bind(&ok);
749 } 844 }
750 // In the integer32 case there are no Smis hidden in heap numbers, so we 845 // In the integer32 case there are no Smis hidden in heap numbers, so we
751 // need only test for Smi zero. 846 // need only test for Smi zero.
752 __ test(value.reg(), Operand(value.reg())); 847 __ test(value.reg(), Operand(value.reg()));
753 dest->false_target()->Branch(zero); 848 dest->false_target()->Branch(zero);
754 value.Unuse(); 849 value.Unuse();
755 dest->Split(not_zero); 850 dest->Split(not_zero);
756 } else if (value.is_number()) { 851 } else if (value.is_number()) {
757 Comment cmnt(masm_, "ONLY_NUMBER"); 852 Comment cmnt(masm_, "ONLY_NUMBER");
758 // Fast case if NumberInfo indicates only numbers. 853 // Fast case if NumberInfo indicates only numbers.
759 if (FLAG_debug_code) { 854 if (FLAG_debug_code) {
760 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); 855 __ AbortIfNotNumber(value.reg());
761 } 856 }
762 // Smi => false iff zero. 857 // Smi => false iff zero.
763 ASSERT(kSmiTag == 0); 858 ASSERT(kSmiTag == 0);
764 __ test(value.reg(), Operand(value.reg())); 859 __ test(value.reg(), Operand(value.reg()));
765 dest->false_target()->Branch(zero); 860 dest->false_target()->Branch(zero);
766 __ test(value.reg(), Immediate(kSmiTagMask)); 861 __ test(value.reg(), Immediate(kSmiTagMask));
767 dest->true_target()->Branch(zero); 862 dest->true_target()->Branch(zero);
768 __ fldz(); 863 __ fldz();
769 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); 864 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
770 __ FCmp(); 865 __ FCmp();
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 Factory::heap_number_map()); 1031 Factory::heap_number_map());
937 __ j(not_equal, &call_runtime); 1032 __ j(not_equal, &call_runtime);
938 } 1033 }
939 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); 1034 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
940 if (mode_ == OVERWRITE_LEFT) { 1035 if (mode_ == OVERWRITE_LEFT) {
941 __ mov(dst_, left_); 1036 __ mov(dst_, left_);
942 } 1037 }
943 __ jmp(&load_right); 1038 __ jmp(&load_right);
944 1039
945 __ bind(&left_smi); 1040 __ bind(&left_smi);
1041 } else {
1042 if (FLAG_debug_code) __ AbortIfNotSmi(left_);
946 } 1043 }
947 __ SmiUntag(left_); 1044 __ SmiUntag(left_);
948 __ cvtsi2sd(xmm0, Operand(left_)); 1045 __ cvtsi2sd(xmm0, Operand(left_));
949 __ SmiTag(left_); 1046 __ SmiTag(left_);
950 if (mode_ == OVERWRITE_LEFT) { 1047 if (mode_ == OVERWRITE_LEFT) {
951 Label alloc_failure; 1048 Label alloc_failure;
952 __ push(left_); 1049 __ push(left_);
953 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 1050 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
954 __ pop(left_); 1051 __ pop(left_);
955 } 1052 }
(...skipping 12 matching lines...) Expand all
968 __ mov(dst_, right_); 1065 __ mov(dst_, right_);
969 } else if (mode_ == NO_OVERWRITE) { 1066 } else if (mode_ == NO_OVERWRITE) {
970 Label alloc_failure; 1067 Label alloc_failure;
971 __ push(left_); 1068 __ push(left_);
972 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 1069 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
973 __ pop(left_); 1070 __ pop(left_);
974 } 1071 }
975 __ jmp(&do_op); 1072 __ jmp(&do_op);
976 1073
977 __ bind(&right_smi); 1074 __ bind(&right_smi);
1075 } else {
1076 if (FLAG_debug_code) __ AbortIfNotSmi(right_);
978 } 1077 }
979 __ SmiUntag(right_); 1078 __ SmiUntag(right_);
980 __ cvtsi2sd(xmm1, Operand(right_)); 1079 __ cvtsi2sd(xmm1, Operand(right_));
981 __ SmiTag(right_); 1080 __ SmiTag(right_);
982 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) { 1081 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
983 Label alloc_failure; 1082 Label alloc_failure;
984 __ push(left_); 1083 __ push(left_);
985 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 1084 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
986 __ pop(left_); 1085 __ pop(left_);
987 } 1086 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 default: 1194 default:
1096 UNREACHABLE(); 1195 UNREACHABLE();
1097 } 1196 }
1098 UNREACHABLE(); 1197 UNREACHABLE();
1099 return NumberInfo::Unknown(); 1198 return NumberInfo::Unknown();
1100 } 1199 }
1101 1200
1102 1201
1103 void CodeGenerator::GenericBinaryOperation(Token::Value op, 1202 void CodeGenerator::GenericBinaryOperation(Token::Value op,
1104 StaticType* type, 1203 StaticType* type,
1105 OverwriteMode overwrite_mode) { 1204 OverwriteMode overwrite_mode,
1205 bool no_negative_zero) {
1106 Comment cmnt(masm_, "[ BinaryOperation"); 1206 Comment cmnt(masm_, "[ BinaryOperation");
1107 Comment cmnt_token(masm_, Token::String(op)); 1207 Comment cmnt_token(masm_, Token::String(op));
1108 1208
1109 if (op == Token::COMMA) { 1209 if (op == Token::COMMA) {
1110 // Simply discard left value. 1210 // Simply discard left value.
1111 frame_->Nip(1); 1211 frame_->Nip(1);
1112 return; 1212 return;
1113 } 1213 }
1114 1214
1115 Result right = frame_->Pop(); 1215 Result right = frame_->Pop();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 Result answer; 1263 Result answer;
1164 if (left_is_non_smi_constant || right_is_non_smi_constant) { 1264 if (left_is_non_smi_constant || right_is_non_smi_constant) {
1165 // Go straight to the slow case, with no smi code. 1265 // Go straight to the slow case, with no smi code.
1166 GenericBinaryOpStub stub(op, 1266 GenericBinaryOpStub stub(op,
1167 overwrite_mode, 1267 overwrite_mode,
1168 NO_SMI_CODE_IN_STUB, 1268 NO_SMI_CODE_IN_STUB,
1169 operands_type); 1269 operands_type);
1170 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1270 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1171 } else if (right_is_smi_constant) { 1271 } else if (right_is_smi_constant) {
1172 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 1272 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
1173 type, false, overwrite_mode); 1273 type, false, overwrite_mode,
1274 no_negative_zero);
1174 } else if (left_is_smi_constant) { 1275 } else if (left_is_smi_constant) {
1175 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 1276 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
1176 type, true, overwrite_mode); 1277 type, true, overwrite_mode,
1278 no_negative_zero);
1177 } else { 1279 } else {
1178 // Set the flags based on the operation, type and loop nesting level. 1280 // Set the flags based on the operation, type and loop nesting level.
1179 // Bit operations always assume they likely operate on Smis. Still only 1281 // Bit operations always assume they likely operate on Smis. Still only
1180 // generate the inline Smi check code if this operation is part of a loop. 1282 // generate the inline Smi check code if this operation is part of a loop.
1181 // For all other operations only inline the Smi check code for likely smis 1283 // For all other operations only inline the Smi check code for likely smis
1182 // if the operation is part of a loop. 1284 // if the operation is part of a loop.
1183 if (loop_nesting() > 0 && 1285 if (loop_nesting() > 0 &&
1184 (Token::IsBitOp(op) || 1286 (Token::IsBitOp(op) ||
1185 operands_type.IsInteger32() || 1287 operands_type.IsInteger32() ||
1186 type->IsLikelySmi())) { 1288 type->IsLikelySmi())) {
1187 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 1289 answer = LikelySmiBinaryOperation(op, &left, &right,
1290 overwrite_mode, no_negative_zero);
1188 } else { 1291 } else {
1189 GenericBinaryOpStub stub(op, 1292 GenericBinaryOpStub stub(op,
1190 overwrite_mode, 1293 overwrite_mode,
1191 NO_GENERIC_BINARY_FLAGS, 1294 NO_GENERIC_BINARY_FLAGS,
1192 operands_type); 1295 operands_type);
1193 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1296 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1194 } 1297 }
1195 } 1298 }
1196 1299
1197 answer.set_number_info(result_type); 1300 answer.set_number_info(result_type);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1284 Register left, Register right, Register scratch, 1387 Register left, Register right, Register scratch,
1285 NumberInfo left_info, NumberInfo right_info, 1388 NumberInfo left_info, NumberInfo right_info,
1286 DeferredInlineBinaryOperation* deferred); 1389 DeferredInlineBinaryOperation* deferred);
1287 1390
1288 1391
1289 // Implements a binary operation using a deferred code object and some 1392 // Implements a binary operation using a deferred code object and some
1290 // inline code to operate on smis quickly. 1393 // inline code to operate on smis quickly.
1291 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 1394 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
1292 Result* left, 1395 Result* left,
1293 Result* right, 1396 Result* right,
1294 OverwriteMode overwrite_mode) { 1397 OverwriteMode overwrite_mode,
1398 bool no_negative_zero) {
1295 Result answer; 1399 Result answer;
1296 // Special handling of div and mod because they use fixed registers. 1400 // Special handling of div and mod because they use fixed registers.
1297 if (op == Token::DIV || op == Token::MOD) { 1401 if (op == Token::DIV || op == Token::MOD) {
1298 // We need eax as the quotient register, edx as the remainder 1402 // We need eax as the quotient register, edx as the remainder
1299 // register, neither left nor right in eax or edx, and left copied 1403 // register, neither left nor right in eax or edx, and left copied
1300 // to eax. 1404 // to eax.
1301 Result quotient; 1405 Result quotient;
1302 Result remainder; 1406 Result remainder;
1303 bool left_is_in_eax = false; 1407 bool left_is_in_eax = false;
1304 // Step 1: get eax for quotient. 1408 // Step 1: get eax for quotient.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 __ test(right->reg(), Operand(right->reg())); 1492 __ test(right->reg(), Operand(right->reg()));
1389 deferred->Branch(zero); 1493 deferred->Branch(zero);
1390 // Divide edx:eax by the right operand. 1494 // Divide edx:eax by the right operand.
1391 __ idiv(right->reg()); 1495 __ idiv(right->reg());
1392 1496
1393 // Complete the operation. 1497 // Complete the operation.
1394 if (op == Token::DIV) { 1498 if (op == Token::DIV) {
1395 // Check for negative zero result. If result is zero, and divisor 1499 // Check for negative zero result. If result is zero, and divisor
1396 // is negative, return a floating point negative zero. The 1500 // is negative, return a floating point negative zero. The
1397 // virtual frame is unchanged in this block, so local control flow 1501 // virtual frame is unchanged in this block, so local control flow
1398 // can use a Label rather than a JumpTarget. 1502 // can use a Label rather than a JumpTarget. If the context of this
1399 Label non_zero_result; 1503 // expression will treat -0 like 0, do not do this test.
1400 __ test(left->reg(), Operand(left->reg())); 1504 if (!no_negative_zero) {
1401 __ j(not_zero, &non_zero_result); 1505 Label non_zero_result;
1402 __ test(right->reg(), Operand(right->reg())); 1506 __ test(left->reg(), Operand(left->reg()));
1403 deferred->Branch(negative); 1507 __ j(not_zero, &non_zero_result);
1404 __ bind(&non_zero_result); 1508 __ test(right->reg(), Operand(right->reg()));
1509 deferred->Branch(negative);
1510 __ bind(&non_zero_result);
1511 }
1405 // Check for the corner case of dividing the most negative smi by 1512 // Check for the corner case of dividing the most negative smi by
1406 // -1. We cannot use the overflow flag, since it is not set by 1513 // -1. We cannot use the overflow flag, since it is not set by
1407 // idiv instruction. 1514 // idiv instruction.
1408 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 1515 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
1409 __ cmp(eax, 0x40000000); 1516 __ cmp(eax, 0x40000000);
1410 deferred->Branch(equal); 1517 deferred->Branch(equal);
1411 // Check that the remainder is zero. 1518 // Check that the remainder is zero.
1412 __ test(edx, Operand(edx)); 1519 __ test(edx, Operand(edx));
1413 deferred->Branch(not_zero); 1520 deferred->Branch(not_zero);
1414 // Tag the result and store it in the quotient register. 1521 // Tag the result and store it in the quotient register.
1415 __ SmiTag(eax); 1522 __ SmiTag(eax);
1416 deferred->BindExit(); 1523 deferred->BindExit();
1417 left->Unuse(); 1524 left->Unuse();
1418 right->Unuse(); 1525 right->Unuse();
1419 answer = quotient; 1526 answer = quotient;
1420 } else { 1527 } else {
1421 ASSERT(op == Token::MOD); 1528 ASSERT(op == Token::MOD);
1422 // Check for a negative zero result. If the result is zero, and 1529 // Check for a negative zero result. If the result is zero, and
1423 // the dividend is negative, return a floating point negative 1530 // the dividend is negative, return a floating point negative
1424 // zero. The frame is unchanged in this block, so local control 1531 // zero. The frame is unchanged in this block, so local control
1425 // flow can use a Label rather than a JumpTarget. 1532 // flow can use a Label rather than a JumpTarget.
1426 Label non_zero_result; 1533 if (!no_negative_zero) {
1427 __ test(edx, Operand(edx)); 1534 Label non_zero_result;
1428 __ j(not_zero, &non_zero_result, taken); 1535 __ test(edx, Operand(edx));
1429 __ test(left->reg(), Operand(left->reg())); 1536 __ j(not_zero, &non_zero_result, taken);
1430 deferred->Branch(negative); 1537 __ test(left->reg(), Operand(left->reg()));
1431 __ bind(&non_zero_result); 1538 deferred->Branch(negative);
1539 __ bind(&non_zero_result);
1540 }
1432 deferred->BindExit(); 1541 deferred->BindExit();
1433 left->Unuse(); 1542 left->Unuse();
1434 right->Unuse(); 1543 right->Unuse();
1435 answer = remainder; 1544 answer = remainder;
1436 } 1545 }
1437 ASSERT(answer.is_valid()); 1546 ASSERT(answer.is_valid());
1438 return answer; 1547 return answer;
1439 } 1548 }
1440 1549
1441 // Special handling of shift operations because they use fixed 1550 // Special handling of shift operations because they use fixed
(...skipping 19 matching lines...) Expand all
1461 // Check that both operands are smis using the answer register as a 1570 // Check that both operands are smis using the answer register as a
1462 // temporary. 1571 // temporary.
1463 DeferredInlineBinaryOperation* deferred = 1572 DeferredInlineBinaryOperation* deferred =
1464 new DeferredInlineBinaryOperation(op, 1573 new DeferredInlineBinaryOperation(op,
1465 answer.reg(), 1574 answer.reg(),
1466 left->reg(), 1575 left->reg(),
1467 ecx, 1576 ecx,
1468 left->number_info(), 1577 left->number_info(),
1469 right->number_info(), 1578 right->number_info(),
1470 overwrite_mode); 1579 overwrite_mode);
1471 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
1472 left->number_info(), right->number_info(), deferred);
1473 1580
1474 // Untag both operands. 1581 Label do_op, left_nonsmi;
1475 __ mov(answer.reg(), left->reg()); 1582 // If right is a smi we make a fast case if left is either a smi
1476 __ SmiUntag(answer.reg()); 1583 // or a heapnumber.
1584 if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) {
1585 CpuFeatures::Scope use_sse2(SSE2);
1586 __ mov(answer.reg(), left->reg());
1587 // Fast case - both are actually smis.
1588 if (!left->number_info().IsSmi()) {
1589 __ test(answer.reg(), Immediate(kSmiTagMask));
1590 __ j(not_zero, &left_nonsmi);
1591 } else {
1592 if (FLAG_debug_code) __ AbortIfNotSmi(left->reg());
1593 }
1594 if (FLAG_debug_code) __ AbortIfNotSmi(right->reg());
1595 __ SmiUntag(answer.reg());
1596 __ jmp(&do_op);
1597
1598 __ bind(&left_nonsmi);
1599 // Branch if not a heapnumber.
1600 __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
1601 Factory::heap_number_map());
1602 deferred->Branch(not_equal);
1603
1604 // Load integer value into answer register using truncation.
1605 __ cvttsd2si(answer.reg(),
1606 FieldOperand(answer.reg(), HeapNumber::kValueOffset));
1607 // Branch if we do not fit in a smi.
1608 __ cmp(answer.reg(), 0xc0000000);
1609 deferred->Branch(negative);
1610 } else {
1611 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
1612 left->number_info(), right->number_info(), deferred);
1613
1614 // Untag both operands.
1615 __ mov(answer.reg(), left->reg());
1616 __ SmiUntag(answer.reg());
1617 }
1618
1619 __ bind(&do_op);
1477 __ SmiUntag(ecx); 1620 __ SmiUntag(ecx);
1478 // Perform the operation. 1621 // Perform the operation.
1479 switch (op) { 1622 switch (op) {
1480 case Token::SAR: 1623 case Token::SAR:
1481 __ sar_cl(answer.reg()); 1624 __ sar_cl(answer.reg());
1482 // No checks of result necessary 1625 // No checks of result necessary
1483 break; 1626 break;
1484 case Token::SHR: { 1627 case Token::SHR: {
1485 Label result_ok; 1628 Label result_ok;
1486 __ shr_cl(answer.reg()); 1629 __ shr_cl(answer.reg());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1564 // Left-hand operand has been copied into answer. 1707 // Left-hand operand has been copied into answer.
1565 __ SmiUntag(answer.reg()); 1708 __ SmiUntag(answer.reg());
1566 // Do multiplication of smis, leaving result in answer. 1709 // Do multiplication of smis, leaving result in answer.
1567 __ imul(answer.reg(), Operand(right->reg())); 1710 __ imul(answer.reg(), Operand(right->reg()));
1568 // Go slow on overflows. 1711 // Go slow on overflows.
1569 deferred->Branch(overflow); 1712 deferred->Branch(overflow);
1570 // Check for negative zero result. If product is zero, and one 1713 // Check for negative zero result. If product is zero, and one
1571 // argument is negative, go to slow case. The frame is unchanged 1714 // argument is negative, go to slow case. The frame is unchanged
1572 // in this block, so local control flow can use a Label rather 1715 // in this block, so local control flow can use a Label rather
1573 // than a JumpTarget. 1716 // than a JumpTarget.
1574 Label non_zero_result; 1717 if (!no_negative_zero) {
1575 __ test(answer.reg(), Operand(answer.reg())); 1718 Label non_zero_result;
1576 __ j(not_zero, &non_zero_result, taken); 1719 __ test(answer.reg(), Operand(answer.reg()));
1577 __ mov(answer.reg(), left->reg()); 1720 __ j(not_zero, &non_zero_result, taken);
1578 __ or_(answer.reg(), Operand(right->reg())); 1721 __ mov(answer.reg(), left->reg());
1579 deferred->Branch(negative); 1722 __ or_(answer.reg(), Operand(right->reg()));
1580 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. 1723 deferred->Branch(negative);
1581 __ bind(&non_zero_result); 1724 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct.
1725 __ bind(&non_zero_result);
1726 }
1582 break; 1727 break;
1583 } 1728 }
1584 1729
1585 case Token::BIT_OR: 1730 case Token::BIT_OR:
1586 __ or_(answer.reg(), Operand(right->reg())); 1731 __ or_(answer.reg(), Operand(right->reg()));
1587 break; 1732 break;
1588 1733
1589 case Token::BIT_AND: 1734 case Token::BIT_AND:
1590 __ and_(answer.reg(), Operand(right->reg())); 1735 __ and_(answer.reg(), Operand(right->reg()));
1591 break; 1736 break;
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 igostub.GenerateCall(masm_, dst_, value_); 1955 igostub.GenerateCall(masm_, dst_, value_);
1811 if (!dst_.is(eax)) __ mov(dst_, eax); 1956 if (!dst_.is(eax)) __ mov(dst_, eax);
1812 } 1957 }
1813 1958
1814 1959
1815 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 1960 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
1816 Result* operand, 1961 Result* operand,
1817 Handle<Object> value, 1962 Handle<Object> value,
1818 StaticType* type, 1963 StaticType* type,
1819 bool reversed, 1964 bool reversed,
1820 OverwriteMode overwrite_mode) { 1965 OverwriteMode overwrite_mode,
1966 bool no_negative_zero) {
1821 // NOTE: This is an attempt to inline (a bit) more of the code for 1967 // NOTE: This is an attempt to inline (a bit) more of the code for
1822 // some possible smi operations (like + and -) when (at least) one 1968 // some possible smi operations (like + and -) when (at least) one
1823 // of the operands is a constant smi. 1969 // of the operands is a constant smi.
1824 // Consumes the argument "operand". 1970 // Consumes the argument "operand".
1825 // TODO(199): Optimize some special cases of operations involving a 1971 // TODO(199): Optimize some special cases of operations involving a
1826 // smi literal (multiply by 2, shift by 0, etc.). 1972 // smi literal (multiply by 2, shift by 0, etc.).
1827 if (IsUnsafeSmi(value)) { 1973 if (IsUnsafeSmi(value)) {
1828 Result unsafe_operand(value); 1974 Result unsafe_operand(value);
1829 if (reversed) { 1975 if (reversed) {
1830 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, 1976 return LikelySmiBinaryOperation(op, &unsafe_operand, operand,
1831 overwrite_mode); 1977 overwrite_mode, no_negative_zero);
1832 } else { 1978 } else {
1833 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, 1979 return LikelySmiBinaryOperation(op, operand, &unsafe_operand,
1834 overwrite_mode); 1980 overwrite_mode, no_negative_zero);
1835 } 1981 }
1836 } 1982 }
1837 1983
1838 // Get the literal value. 1984 // Get the literal value.
1839 Smi* smi_value = Smi::cast(*value); 1985 Smi* smi_value = Smi::cast(*value);
1840 int int_value = smi_value->value(); 1986 int int_value = smi_value->value();
1841 1987
1842 Result answer; 1988 Result answer;
1843 switch (op) { 1989 switch (op) {
1844 case Token::ADD: { 1990 case Token::ADD: {
(...skipping 12 matching lines...) Expand all
1857 deferred = new DeferredInlineSmiAdd(operand->reg(), 2003 deferred = new DeferredInlineSmiAdd(operand->reg(),
1858 operand->number_info(), 2004 operand->number_info(),
1859 smi_value, 2005 smi_value,
1860 overwrite_mode); 2006 overwrite_mode);
1861 } 2007 }
1862 __ add(Operand(operand->reg()), Immediate(value)); 2008 __ add(Operand(operand->reg()), Immediate(value));
1863 deferred->Branch(overflow); 2009 deferred->Branch(overflow);
1864 if (!operand->number_info().IsSmi()) { 2010 if (!operand->number_info().IsSmi()) {
1865 __ test(operand->reg(), Immediate(kSmiTagMask)); 2011 __ test(operand->reg(), Immediate(kSmiTagMask));
1866 deferred->Branch(not_zero); 2012 deferred->Branch(not_zero);
2013 } else {
2014 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
1867 } 2015 }
1868 deferred->BindExit(); 2016 deferred->BindExit();
1869 answer = *operand; 2017 answer = *operand;
1870 break; 2018 break;
1871 } 2019 }
1872 2020
1873 case Token::SUB: { 2021 case Token::SUB: {
1874 DeferredCode* deferred = NULL; 2022 DeferredCode* deferred = NULL;
1875 if (reversed) { 2023 if (reversed) {
1876 // The reversed case is only hit when the right operand is not a 2024 // The reversed case is only hit when the right operand is not a
(...skipping 17 matching lines...) Expand all
1894 deferred = new DeferredInlineSmiSub(operand->reg(), 2042 deferred = new DeferredInlineSmiSub(operand->reg(),
1895 operand->number_info(), 2043 operand->number_info(),
1896 smi_value, 2044 smi_value,
1897 overwrite_mode); 2045 overwrite_mode);
1898 __ sub(Operand(operand->reg()), Immediate(value)); 2046 __ sub(Operand(operand->reg()), Immediate(value));
1899 } 2047 }
1900 deferred->Branch(overflow); 2048 deferred->Branch(overflow);
1901 if (!operand->number_info().IsSmi()) { 2049 if (!operand->number_info().IsSmi()) {
1902 __ test(answer.reg(), Immediate(kSmiTagMask)); 2050 __ test(answer.reg(), Immediate(kSmiTagMask));
1903 deferred->Branch(not_zero); 2051 deferred->Branch(not_zero);
2052 } else {
2053 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
1904 } 2054 }
1905 deferred->BindExit(); 2055 deferred->BindExit();
1906 operand->Unuse(); 2056 operand->Unuse();
1907 break; 2057 break;
1908 } 2058 }
1909 2059
1910 case Token::SAR: 2060 case Token::SAR:
1911 if (reversed) { 2061 if (reversed) {
1912 Result constant_operand(value); 2062 Result constant_operand(value);
1913 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 2063 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1914 overwrite_mode); 2064 overwrite_mode, no_negative_zero);
1915 } else { 2065 } else {
1916 // Only the least significant 5 bits of the shift value are used. 2066 // Only the least significant 5 bits of the shift value are used.
1917 // In the slow case, this masking is done inside the runtime call. 2067 // In the slow case, this masking is done inside the runtime call.
1918 int shift_value = int_value & 0x1f; 2068 int shift_value = int_value & 0x1f;
1919 operand->ToRegister(); 2069 operand->ToRegister();
1920 frame_->Spill(operand->reg()); 2070 frame_->Spill(operand->reg());
1921 if (!operand->number_info().IsSmi()) { 2071 if (!operand->number_info().IsSmi()) {
1922 DeferredInlineSmiOperation* deferred = 2072 DeferredInlineSmiOperation* deferred =
1923 new DeferredInlineSmiOperation(op, 2073 new DeferredInlineSmiOperation(op,
1924 operand->reg(), 2074 operand->reg(),
1925 operand->reg(), 2075 operand->reg(),
1926 operand->number_info(), 2076 operand->number_info(),
1927 smi_value, 2077 smi_value,
1928 overwrite_mode); 2078 overwrite_mode);
1929 __ test(operand->reg(), Immediate(kSmiTagMask)); 2079 __ test(operand->reg(), Immediate(kSmiTagMask));
1930 deferred->Branch(not_zero); 2080 deferred->Branch(not_zero);
1931 if (shift_value > 0) { 2081 if (shift_value > 0) {
1932 __ sar(operand->reg(), shift_value); 2082 __ sar(operand->reg(), shift_value);
1933 __ and_(operand->reg(), ~kSmiTagMask); 2083 __ and_(operand->reg(), ~kSmiTagMask);
1934 } 2084 }
1935 deferred->BindExit(); 2085 deferred->BindExit();
1936 } else { 2086 } else {
2087 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
1937 if (shift_value > 0) { 2088 if (shift_value > 0) {
1938 __ sar(operand->reg(), shift_value); 2089 __ sar(operand->reg(), shift_value);
1939 __ and_(operand->reg(), ~kSmiTagMask); 2090 __ and_(operand->reg(), ~kSmiTagMask);
1940 } 2091 }
1941 } 2092 }
1942 answer = *operand; 2093 answer = *operand;
1943 } 2094 }
1944 break; 2095 break;
1945 2096
1946 case Token::SHR: 2097 case Token::SHR:
1947 if (reversed) { 2098 if (reversed) {
1948 Result constant_operand(value); 2099 Result constant_operand(value);
1949 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 2100 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1950 overwrite_mode); 2101 overwrite_mode, no_negative_zero);
1951 } else { 2102 } else {
1952 // Only the least significant 5 bits of the shift value are used. 2103 // Only the least significant 5 bits of the shift value are used.
1953 // In the slow case, this masking is done inside the runtime call. 2104 // In the slow case, this masking is done inside the runtime call.
1954 int shift_value = int_value & 0x1f; 2105 int shift_value = int_value & 0x1f;
1955 operand->ToRegister(); 2106 operand->ToRegister();
1956 answer = allocator()->Allocate(); 2107 answer = allocator()->Allocate();
1957 ASSERT(answer.is_valid()); 2108 ASSERT(answer.is_valid());
1958 DeferredInlineSmiOperation* deferred = 2109 DeferredInlineSmiOperation* deferred =
1959 new DeferredInlineSmiOperation(op, 2110 new DeferredInlineSmiOperation(op,
1960 answer.reg(), 2111 answer.reg(),
1961 operand->reg(), 2112 operand->reg(),
1962 operand->number_info(), 2113 operand->number_info(),
1963 smi_value, 2114 smi_value,
1964 overwrite_mode); 2115 overwrite_mode);
1965 if (!operand->number_info().IsSmi()) { 2116 if (!operand->number_info().IsSmi()) {
1966 __ test(operand->reg(), Immediate(kSmiTagMask)); 2117 __ test(operand->reg(), Immediate(kSmiTagMask));
1967 deferred->Branch(not_zero); 2118 deferred->Branch(not_zero);
2119 } else {
2120 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
1968 } 2121 }
1969 __ mov(answer.reg(), operand->reg()); 2122 __ mov(answer.reg(), operand->reg());
1970 __ SmiUntag(answer.reg()); 2123 __ SmiUntag(answer.reg());
1971 __ shr(answer.reg(), shift_value); 2124 __ shr(answer.reg(), shift_value);
1972 // A negative Smi shifted right two is in the positive Smi range. 2125 // A negative Smi shifted right two is in the positive Smi range.
1973 if (shift_value < 2) { 2126 if (shift_value < 2) {
1974 __ test(answer.reg(), Immediate(0xc0000000)); 2127 __ test(answer.reg(), Immediate(0xc0000000));
1975 deferred->Branch(not_zero); 2128 deferred->Branch(not_zero);
1976 } 2129 }
1977 operand->Unuse(); 2130 operand->Unuse();
(...skipping 28 matching lines...) Expand all
2006 new DeferredInlineSmiOperationReversed(op, 2159 new DeferredInlineSmiOperationReversed(op,
2007 answer.reg(), 2160 answer.reg(),
2008 smi_value, 2161 smi_value,
2009 right.reg(), 2162 right.reg(),
2010 right.number_info(), 2163 right.number_info(),
2011 overwrite_mode); 2164 overwrite_mode);
2012 __ mov(answer.reg(), Immediate(int_value)); 2165 __ mov(answer.reg(), Immediate(int_value));
2013 __ sar(ecx, kSmiTagSize); 2166 __ sar(ecx, kSmiTagSize);
2014 if (!right.number_info().IsSmi()) { 2167 if (!right.number_info().IsSmi()) {
2015 deferred->Branch(carry); 2168 deferred->Branch(carry);
2169 } else {
2170 if (FLAG_debug_code) __ AbortIfNotSmi(right.reg());
2016 } 2171 }
2017 __ shl_cl(answer.reg()); 2172 __ shl_cl(answer.reg());
2018 __ cmp(answer.reg(), 0xc0000000); 2173 __ cmp(answer.reg(), 0xc0000000);
2019 deferred->Branch(sign); 2174 deferred->Branch(sign);
2020 __ SmiTag(answer.reg()); 2175 __ SmiTag(answer.reg());
2021 2176
2022 deferred->BindExit(); 2177 deferred->BindExit();
2023 } else { 2178 } else {
2024 // Only the least significant 5 bits of the shift value are used. 2179 // Only the least significant 5 bits of the shift value are used.
2025 // In the slow case, this masking is done inside the runtime call. 2180 // In the slow case, this masking is done inside the runtime call.
(...skipping 20 matching lines...) Expand all
2046 DeferredInlineSmiOperation* deferred = 2201 DeferredInlineSmiOperation* deferred =
2047 new DeferredInlineSmiOperation(op, 2202 new DeferredInlineSmiOperation(op,
2048 answer.reg(), 2203 answer.reg(),
2049 operand->reg(), 2204 operand->reg(),
2050 operand->number_info(), 2205 operand->number_info(),
2051 smi_value, 2206 smi_value,
2052 overwrite_mode); 2207 overwrite_mode);
2053 if (!operand->number_info().IsSmi()) { 2208 if (!operand->number_info().IsSmi()) {
2054 __ test(operand->reg(), Immediate(kSmiTagMask)); 2209 __ test(operand->reg(), Immediate(kSmiTagMask));
2055 deferred->Branch(not_zero); 2210 deferred->Branch(not_zero);
2211 } else {
2212 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
2056 } 2213 }
2057 __ mov(answer.reg(), operand->reg()); 2214 __ mov(answer.reg(), operand->reg());
2058 ASSERT(kSmiTag == 0); // adjust code if not the case 2215 ASSERT(kSmiTag == 0); // adjust code if not the case
2059 // We do no shifts, only the Smi conversion, if shift_value is 1. 2216 // We do no shifts, only the Smi conversion, if shift_value is 1.
2060 if (shift_value > 1) { 2217 if (shift_value > 1) {
2061 __ shl(answer.reg(), shift_value - 1); 2218 __ shl(answer.reg(), shift_value - 1);
2062 } 2219 }
2063 // Convert int result to Smi, checking that it is in int range. 2220 // Convert int result to Smi, checking that it is in int range.
2064 ASSERT(kSmiTagSize == 1); // adjust code if not the case 2221 ASSERT(kSmiTagSize == 1); // adjust code if not the case
2065 __ add(answer.reg(), Operand(answer.reg())); 2222 __ add(answer.reg(), Operand(answer.reg()));
(...skipping 22 matching lines...) Expand all
2088 deferred = new DeferredInlineSmiOperation(op, 2245 deferred = new DeferredInlineSmiOperation(op,
2089 operand->reg(), 2246 operand->reg(),
2090 operand->reg(), 2247 operand->reg(),
2091 operand->number_info(), 2248 operand->number_info(),
2092 smi_value, 2249 smi_value,
2093 overwrite_mode); 2250 overwrite_mode);
2094 } 2251 }
2095 if (!operand->number_info().IsSmi()) { 2252 if (!operand->number_info().IsSmi()) {
2096 __ test(operand->reg(), Immediate(kSmiTagMask)); 2253 __ test(operand->reg(), Immediate(kSmiTagMask));
2097 deferred->Branch(not_zero); 2254 deferred->Branch(not_zero);
2255 } else {
2256 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
2098 } 2257 }
2099 if (op == Token::BIT_AND) { 2258 if (op == Token::BIT_AND) {
2100 __ and_(Operand(operand->reg()), Immediate(value)); 2259 __ and_(Operand(operand->reg()), Immediate(value));
2101 } else if (op == Token::BIT_XOR) { 2260 } else if (op == Token::BIT_XOR) {
2102 if (int_value != 0) { 2261 if (int_value != 0) {
2103 __ xor_(Operand(operand->reg()), Immediate(value)); 2262 __ xor_(Operand(operand->reg()), Immediate(value));
2104 } 2263 }
2105 } else { 2264 } else {
2106 ASSERT(op == Token::BIT_OR); 2265 ASSERT(op == Token::BIT_OR);
2107 if (int_value != 0) { 2266 if (int_value != 0) {
(...skipping 25 matching lines...) Expand all
2133 deferred->Branch(not_zero); // Branch if non-smi or odd smi. 2292 deferred->Branch(not_zero); // Branch if non-smi or odd smi.
2134 __ sar(operand->reg(), 1); 2293 __ sar(operand->reg(), 1);
2135 deferred->BindExit(); 2294 deferred->BindExit();
2136 answer = *operand; 2295 answer = *operand;
2137 } else { 2296 } else {
2138 // Cannot fall through MOD to default case, so we duplicate the 2297 // Cannot fall through MOD to default case, so we duplicate the
2139 // default case here. 2298 // default case here.
2140 Result constant_operand(value); 2299 Result constant_operand(value);
2141 if (reversed) { 2300 if (reversed) {
2142 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 2301 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
2143 overwrite_mode); 2302 overwrite_mode, no_negative_zero);
2144 } else { 2303 } else {
2145 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, 2304 answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
2146 overwrite_mode); 2305 overwrite_mode, no_negative_zero);
2147 } 2306 }
2148 } 2307 }
2149 break; 2308 break;
2150 // Generate inline code for mod of powers of 2 and negative powers of 2. 2309 // Generate inline code for mod of powers of 2 and negative powers of 2.
2151 case Token::MOD: 2310 case Token::MOD:
2152 if (!reversed && 2311 if (!reversed &&
2153 int_value != 0 && 2312 int_value != 0 &&
2154 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { 2313 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
2155 operand->ToRegister(); 2314 operand->ToRegister();
2156 frame_->Spill(operand->reg()); 2315 frame_->Spill(operand->reg());
(...skipping 16 matching lines...) Expand all
2173 deferred->BindExit(); 2332 deferred->BindExit();
2174 answer = *operand; 2333 answer = *operand;
2175 break; 2334 break;
2176 } 2335 }
2177 // Fall through if we did not find a power of 2 on the right hand side! 2336 // Fall through if we did not find a power of 2 on the right hand side!
2178 2337
2179 default: { 2338 default: {
2180 Result constant_operand(value); 2339 Result constant_operand(value);
2181 if (reversed) { 2340 if (reversed) {
2182 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 2341 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
2183 overwrite_mode); 2342 overwrite_mode, no_negative_zero);
2184 } else { 2343 } else {
2185 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, 2344 answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
2186 overwrite_mode); 2345 overwrite_mode, no_negative_zero);
2187 } 2346 }
2188 break; 2347 break;
2189 } 2348 }
2190 } 2349 }
2191 ASSERT(answer.is_valid()); 2350 ASSERT(answer.is_valid());
2192 return answer; 2351 return answer;
2193 } 2352 }
2194 2353
2195 2354
2196 static bool CouldBeNaN(const Result& result) { 2355 static bool CouldBeNaN(const Result& result) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2279 // where both sides are Smis. 2438 // where both sides are Smis.
2280 left_side.ToRegister(); 2439 left_side.ToRegister();
2281 Register left_reg = left_side.reg(); 2440 Register left_reg = left_side.reg();
2282 Handle<Object> right_val = right_side.handle(); 2441 Handle<Object> right_val = right_side.handle();
2283 2442
2284 // Here we split control flow to the stub call and inlined cases 2443 // Here we split control flow to the stub call and inlined cases
2285 // before finally splitting it to the control destination. We use 2444 // before finally splitting it to the control destination. We use
2286 // a jump target and branching to duplicate the virtual frame at 2445 // a jump target and branching to duplicate the virtual frame at
2287 // the first split. We manually handle the off-frame references 2446 // the first split. We manually handle the off-frame references
2288 // by reconstituting them on the non-fall-through path. 2447 // by reconstituting them on the non-fall-through path.
2289 JumpTarget is_smi;
2290 __ test(left_side.reg(), Immediate(kSmiTagMask));
2291 is_smi.Branch(zero, taken);
2292 2448
2293 bool is_for_loop_compare = (node->AsCompareOperation() != NULL) 2449 if (left_side.is_smi()) {
2294 && node->AsCompareOperation()->is_for_loop_condition(); 2450 if (FLAG_debug_code) __ AbortIfNotSmi(left_side.reg());
2295 if (!is_for_loop_compare 2451 } else {
2296 && CpuFeatures::IsSupported(SSE2) 2452 JumpTarget is_smi;
2297 && right_val->IsSmi()) { 2453 __ test(left_side.reg(), Immediate(kSmiTagMask));
2298 // Right side is a constant smi and left side has been checked 2454 is_smi.Branch(zero, taken);
2299 // not to be a smi. 2455
2300 CpuFeatures::Scope use_sse2(SSE2); 2456 bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
2301 JumpTarget not_number; 2457 && node->AsCompareOperation()->is_for_loop_condition();
2302 __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset), 2458 if (!is_for_loop_compare
2303 Immediate(Factory::heap_number_map())); 2459 && CpuFeatures::IsSupported(SSE2)
2304 not_number.Branch(not_equal, &left_side); 2460 && right_val->IsSmi()) {
2305 __ movdbl(xmm1, 2461 // Right side is a constant smi and left side has been checked
2306 FieldOperand(left_reg, HeapNumber::kValueOffset)); 2462 // not to be a smi.
2307 int value = Smi::cast(*right_val)->value(); 2463 CpuFeatures::Scope use_sse2(SSE2);
2308 if (value == 0) { 2464 JumpTarget not_number;
2309 __ xorpd(xmm0, xmm0); 2465 __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
2310 } else { 2466 Immediate(Factory::heap_number_map()));
2311 Result temp = allocator()->Allocate(); 2467 not_number.Branch(not_equal, &left_side);
2312 __ mov(temp.reg(), Immediate(value)); 2468 __ movdbl(xmm1,
2313 __ cvtsi2sd(xmm0, Operand(temp.reg())); 2469 FieldOperand(left_reg, HeapNumber::kValueOffset));
2314 temp.Unuse(); 2470 int value = Smi::cast(*right_val)->value();
2471 if (value == 0) {
2472 __ xorpd(xmm0, xmm0);
2473 } else {
2474 Result temp = allocator()->Allocate();
2475 __ mov(temp.reg(), Immediate(value));
2476 __ cvtsi2sd(xmm0, Operand(temp.reg()));
2477 temp.Unuse();
2478 }
2479 __ comisd(xmm1, xmm0);
2480 // Jump to builtin for NaN.
2481 not_number.Branch(parity_even, &left_side);
2482 left_side.Unuse();
2483 Condition double_cc = cc;
2484 switch (cc) {
2485 case less: double_cc = below; break;
2486 case equal: double_cc = equal; break;
2487 case less_equal: double_cc = below_equal; break;
2488 case greater: double_cc = above; break;
2489 case greater_equal: double_cc = above_equal; break;
2490 default: UNREACHABLE();
2491 }
2492 dest->true_target()->Branch(double_cc);
2493 dest->false_target()->Jump();
2494 not_number.Bind(&left_side);
2315 } 2495 }
2316 __ comisd(xmm1, xmm0); 2496
2317 // Jump to builtin for NaN. 2497 // Setup and call the compare stub.
2318 not_number.Branch(parity_even, &left_side); 2498 CompareStub stub(cc, strict, kCantBothBeNaN);
2319 left_side.Unuse(); 2499 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2320 Condition double_cc = cc; 2500 result.ToRegister();
2321 switch (cc) { 2501 __ cmp(result.reg(), 0);
2322 case less: double_cc = below; break; 2502 result.Unuse();
2323 case equal: double_cc = equal; break; 2503 dest->true_target()->Branch(cc);
2324 case less_equal: double_cc = below_equal; break;
2325 case greater: double_cc = above; break;
2326 case greater_equal: double_cc = above_equal; break;
2327 default: UNREACHABLE();
2328 }
2329 dest->true_target()->Branch(double_cc);
2330 dest->false_target()->Jump(); 2504 dest->false_target()->Jump();
2331 not_number.Bind(&left_side); 2505
2506 is_smi.Bind();
2332 } 2507 }
2333 2508
2334 // Setup and call the compare stub.
2335 CompareStub stub(cc, strict, kCantBothBeNaN);
2336 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2337 result.ToRegister();
2338 __ cmp(result.reg(), 0);
2339 result.Unuse();
2340 dest->true_target()->Branch(cc);
2341 dest->false_target()->Jump();
2342
2343 is_smi.Bind();
2344 left_side = Result(left_reg); 2509 left_side = Result(left_reg);
2345 right_side = Result(right_val); 2510 right_side = Result(right_val);
2346 // Test smi equality and comparison by signed int comparison. 2511 // Test smi equality and comparison by signed int comparison.
2347 if (IsUnsafeSmi(right_side.handle())) { 2512 if (IsUnsafeSmi(right_side.handle())) {
2348 right_side.ToRegister(); 2513 right_side.ToRegister();
2349 __ cmp(left_side.reg(), Operand(right_side.reg())); 2514 __ cmp(left_side.reg(), Operand(right_side.reg()));
2350 } else { 2515 } else {
2351 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); 2516 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle()));
2352 } 2517 }
2353 left_side.Unuse(); 2518 left_side.Unuse();
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 3645
3481 // The break target may be already bound (by the condition), or there 3646 // The break target may be already bound (by the condition), or there
3482 // may not be a valid frame. Bind it only if needed. 3647 // may not be a valid frame. Bind it only if needed.
3483 if (node->break_target()->is_linked()) { 3648 if (node->break_target()->is_linked()) {
3484 node->break_target()->Bind(); 3649 node->break_target()->Bind();
3485 } 3650 }
3486 DecrementLoopNesting(); 3651 DecrementLoopNesting();
3487 } 3652 }
3488 3653
3489 3654
3655 void CodeGenerator::SetTypeForStackSlot(Slot* slot, NumberInfo info) {
3656 ASSERT(slot->type() == Slot::LOCAL || slot->type() == Slot::PARAMETER);
3657 if (slot->type() == Slot::LOCAL) {
3658 frame_->SetTypeForLocalAt(slot->index(), info);
3659 } else {
3660 frame_->SetTypeForParamAt(slot->index(), info);
3661 }
3662 if (FLAG_debug_code && info.IsSmi()) {
3663 if (slot->type() == Slot::LOCAL) {
3664 frame_->PushLocalAt(slot->index());
3665 } else {
3666 frame_->PushParameterAt(slot->index());
3667 }
3668 Result var = frame_->Pop();
3669 var.ToRegister();
3670 __ AbortIfNotSmi(var.reg());
3671 }
3672 }
3673
3674
3490 void CodeGenerator::VisitForStatement(ForStatement* node) { 3675 void CodeGenerator::VisitForStatement(ForStatement* node) {
3491 ASSERT(!in_spilled_code()); 3676 ASSERT(!in_spilled_code());
3492 Comment cmnt(masm_, "[ ForStatement"); 3677 Comment cmnt(masm_, "[ ForStatement");
3493 CodeForStatementPosition(node); 3678 CodeForStatementPosition(node);
3494 3679
3495 // Compile the init expression if present. 3680 // Compile the init expression if present.
3496 if (node->init() != NULL) { 3681 if (node->init() != NULL) {
3497 Visit(node->init()); 3682 Visit(node->init());
3498 } 3683 }
3499 3684
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3572 body.Bind(); 3757 body.Bind();
3573 } 3758 }
3574 break; 3759 break;
3575 } 3760 }
3576 case ALWAYS_FALSE: 3761 case ALWAYS_FALSE:
3577 UNREACHABLE(); 3762 UNREACHABLE();
3578 break; 3763 break;
3579 } 3764 }
3580 3765
3581 CheckStack(); // TODO(1222600): ignore if body contains calls. 3766 CheckStack(); // TODO(1222600): ignore if body contains calls.
3767
3768 // We know that the loop index is a smi if it is not modified in the
3769 // loop body and it is checked against a constant limit in the loop
3770 // condition. In this case, we reset the static type information of the
3771 // loop index to smi before compiling the body, the update expression, and
3772 // the bottom check of the loop condition.
3773 if (node->is_fast_smi_loop()) {
3774 // Set number type of the loop variable to smi.
3775 SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi());
3776 }
3777
3582 Visit(node->body()); 3778 Visit(node->body());
3583 3779
3584 // If there is an update expression, compile it if necessary. 3780 // If there is an update expression, compile it if necessary.
3585 if (node->next() != NULL) { 3781 if (node->next() != NULL) {
3586 if (node->continue_target()->is_linked()) { 3782 if (node->continue_target()->is_linked()) {
3587 node->continue_target()->Bind(); 3783 node->continue_target()->Bind();
3588 } 3784 }
3589 3785
3590 // Control can reach the update by falling out of the body or by a 3786 // Control can reach the update by falling out of the body or by a
3591 // continue. 3787 // continue.
3592 if (has_valid_frame()) { 3788 if (has_valid_frame()) {
3593 // Record the source position of the statement as this code which 3789 // Record the source position of the statement as this code which
3594 // is after the code for the body actually belongs to the loop 3790 // is after the code for the body actually belongs to the loop
3595 // statement and not the body. 3791 // statement and not the body.
3596 CodeForStatementPosition(node); 3792 CodeForStatementPosition(node);
3597 Visit(node->next()); 3793 Visit(node->next());
3598 } 3794 }
3599 } 3795 }
3600 3796
3797 // Set the type of the loop variable to smi before compiling the test
3798 // expression if we are in a fast smi loop condition.
3799 if (node->is_fast_smi_loop() && has_valid_frame()) {
3800 // Set number type of the loop variable to smi.
3801 SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi());
3802 }
3803
3601 // Based on the condition analysis, compile the backward jump as 3804 // Based on the condition analysis, compile the backward jump as
3602 // necessary. 3805 // necessary.
3603 switch (info) { 3806 switch (info) {
3604 case ALWAYS_TRUE: 3807 case ALWAYS_TRUE:
3605 if (has_valid_frame()) { 3808 if (has_valid_frame()) {
3606 if (node->next() == NULL) { 3809 if (node->next() == NULL) {
3607 node->continue_target()->Jump(); 3810 node->continue_target()->Jump();
3608 } else { 3811 } else {
3609 loop.Jump(); 3812 loop.Jump();
3610 } 3813 }
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 // object. 4440 // object.
4238 frame()->EmitPush(esi); 4441 frame()->EmitPush(esi);
4239 frame()->EmitPush(Immediate(boilerplate)); 4442 frame()->EmitPush(Immediate(boilerplate));
4240 return frame()->CallRuntime(Runtime::kNewClosure, 2); 4443 return frame()->CallRuntime(Runtime::kNewClosure, 2);
4241 } 4444 }
4242 } 4445 }
4243 4446
4244 4447
4245 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 4448 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
4246 Comment cmnt(masm_, "[ FunctionLiteral"); 4449 Comment cmnt(masm_, "[ FunctionLiteral");
4247 4450 ASSERT(!in_safe_int32_mode());
4248 // Build the function boilerplate and instantiate it. 4451 // Build the function boilerplate and instantiate it.
4249 Handle<JSFunction> boilerplate = 4452 Handle<JSFunction> boilerplate =
4250 Compiler::BuildBoilerplate(node, script(), this); 4453 Compiler::BuildBoilerplate(node, script(), this);
4251 // Check for stack-overflow exception. 4454 // Check for stack-overflow exception.
4252 if (HasStackOverflow()) return; 4455 if (HasStackOverflow()) return;
4253 Result result = InstantiateBoilerplate(boilerplate); 4456 Result result = InstantiateBoilerplate(boilerplate);
4254 frame()->Push(&result); 4457 frame()->Push(&result);
4255 } 4458 }
4256 4459
4257 4460
4258 void CodeGenerator::VisitFunctionBoilerplateLiteral( 4461 void CodeGenerator::VisitFunctionBoilerplateLiteral(
4259 FunctionBoilerplateLiteral* node) { 4462 FunctionBoilerplateLiteral* node) {
4463 ASSERT(!in_safe_int32_mode());
4260 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 4464 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
4261 Result result = InstantiateBoilerplate(node->boilerplate()); 4465 Result result = InstantiateBoilerplate(node->boilerplate());
4262 frame()->Push(&result); 4466 frame()->Push(&result);
4263 } 4467 }
4264 4468
4265 4469
4266 void CodeGenerator::VisitConditional(Conditional* node) { 4470 void CodeGenerator::VisitConditional(Conditional* node) {
4267 Comment cmnt(masm_, "[ Conditional"); 4471 Comment cmnt(masm_, "[ Conditional");
4472 ASSERT(!in_safe_int32_mode());
4268 JumpTarget then; 4473 JumpTarget then;
4269 JumpTarget else_; 4474 JumpTarget else_;
4270 JumpTarget exit; 4475 JumpTarget exit;
4271 ControlDestination dest(&then, &else_, true); 4476 ControlDestination dest(&then, &else_, true);
4272 LoadCondition(node->condition(), &dest, true); 4477 LoadCondition(node->condition(), &dest, true);
4273 4478
4274 if (dest.false_was_fall_through()) { 4479 if (dest.false_was_fall_through()) {
4275 // The else target was bound, so we compile the else part first. 4480 // The else target was bound, so we compile the else part first.
4276 Load(node->else_expression()); 4481 Load(node->else_expression());
4277 4482
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
4428 result = StoreArgumentsObject(false); 4633 result = StoreArgumentsObject(false);
4429 exit.Bind(&result); 4634 exit.Bind(&result);
4430 return result; 4635 return result;
4431 } 4636 }
4432 4637
4433 4638
4434 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 4639 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
4435 Slot* slot, 4640 Slot* slot,
4436 TypeofState typeof_state, 4641 TypeofState typeof_state,
4437 JumpTarget* slow) { 4642 JumpTarget* slow) {
4643 ASSERT(!in_safe_int32_mode());
4438 // Check that no extension objects have been created by calls to 4644 // Check that no extension objects have been created by calls to
4439 // eval from the current scope to the global scope. 4645 // eval from the current scope to the global scope.
4440 Register context = esi; 4646 Register context = esi;
4441 Result tmp = allocator_->Allocate(); 4647 Result tmp = allocator_->Allocate();
4442 ASSERT(tmp.is_valid()); // All non-reserved registers were available. 4648 ASSERT(tmp.is_valid()); // All non-reserved registers were available.
4443 4649
4444 Scope* s = scope(); 4650 Scope* s = scope();
4445 while (s != NULL) { 4651 while (s != NULL) {
4446 if (s->num_heap_slots() > 0) { 4652 if (s->num_heap_slots() > 0) {
4447 if (s->calls_eval()) { 4653 if (s->calls_eval()) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
4596 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg()); 4802 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
4597 // The results start, value, and temp are unused by going out of 4803 // The results start, value, and temp are unused by going out of
4598 // scope. 4804 // scope.
4599 } 4805 }
4600 4806
4601 exit.Bind(); 4807 exit.Bind();
4602 } 4808 }
4603 } 4809 }
4604 4810
4605 4811
4606 void CodeGenerator::VisitSlot(Slot* node) { 4812 void CodeGenerator::VisitSlot(Slot* slot) {
4607 Comment cmnt(masm_, "[ Slot"); 4813 Comment cmnt(masm_, "[ Slot");
4608 Result result = LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); 4814 if (in_safe_int32_mode()) {
4609 frame()->Push(&result); 4815 if ((slot->type() == Slot::LOCAL && !slot->is_arguments())) {
4816 frame()->UntaggedPushLocalAt(slot->index());
4817 } else if (slot->type() == Slot::PARAMETER) {
4818 frame()->UntaggedPushParameterAt(slot->index());
4819 } else {
4820 UNREACHABLE();
4821 }
4822 } else {
4823 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
4824 frame()->Push(&result);
4825 }
4610 } 4826 }
4611 4827
4612 4828
4613 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 4829 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
4614 Comment cmnt(masm_, "[ VariableProxy"); 4830 Comment cmnt(masm_, "[ VariableProxy");
4615 Variable* var = node->var(); 4831 Variable* var = node->var();
4616 Expression* expr = var->rewrite(); 4832 Expression* expr = var->rewrite();
4617 if (expr != NULL) { 4833 if (expr != NULL) {
4618 Visit(expr); 4834 Visit(expr);
4619 } else { 4835 } else {
4620 ASSERT(var->is_global()); 4836 ASSERT(var->is_global());
4837 ASSERT(!in_safe_int32_mode());
4621 Reference ref(this, node); 4838 Reference ref(this, node);
4622 ref.GetValue(); 4839 ref.GetValue();
4623 } 4840 }
4624 } 4841 }
4625 4842
4626 4843
4627 void CodeGenerator::VisitLiteral(Literal* node) { 4844 void CodeGenerator::VisitLiteral(Literal* node) {
4628 Comment cmnt(masm_, "[ Literal"); 4845 Comment cmnt(masm_, "[ Literal");
4629 frame_->Push(node->handle()); 4846 if (in_safe_int32_mode()) {
4847 frame_->PushUntaggedElement(node->handle());
4848 } else {
4849 frame_->Push(node->handle());
4850 }
4630 } 4851 }
4631 4852
4632 4853
4633 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) { 4854 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
4634 ASSERT(value->IsSmi()); 4855 ASSERT(value->IsSmi());
4635 int bits = reinterpret_cast<int>(*value); 4856 int bits = reinterpret_cast<int>(*value);
4636 __ push(Immediate(bits & 0x0000FFFF)); 4857 __ push(Immediate(bits & 0x0000FFFF));
4637 __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000)); 4858 __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000));
4638 } 4859 }
4639 4860
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4693 // RegExp pattern (2). 4914 // RegExp pattern (2).
4694 __ push(Immediate(node_->pattern())); 4915 __ push(Immediate(node_->pattern()));
4695 // RegExp flags (3). 4916 // RegExp flags (3).
4696 __ push(Immediate(node_->flags())); 4917 __ push(Immediate(node_->flags()));
4697 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 4918 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
4698 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); 4919 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax);
4699 } 4920 }
4700 4921
4701 4922
4702 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 4923 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
4924 ASSERT(!in_safe_int32_mode());
4703 Comment cmnt(masm_, "[ RegExp Literal"); 4925 Comment cmnt(masm_, "[ RegExp Literal");
4704 4926
4705 // Retrieve the literals array and check the allocated entry. Begin 4927 // Retrieve the literals array and check the allocated entry. Begin
4706 // with a writable copy of the function of this activation in a 4928 // with a writable copy of the function of this activation in a
4707 // register. 4929 // register.
4708 frame_->PushFunction(); 4930 frame_->PushFunction();
4709 Result literals = frame_->Pop(); 4931 Result literals = frame_->Pop();
4710 literals.ToRegister(); 4932 literals.ToRegister();
4711 frame_->Spill(literals.reg()); 4933 frame_->Spill(literals.reg());
4712 4934
(...skipping 16 matching lines...) Expand all
4729 deferred->Branch(equal); 4951 deferred->Branch(equal);
4730 deferred->BindExit(); 4952 deferred->BindExit();
4731 literals.Unuse(); 4953 literals.Unuse();
4732 4954
4733 // Push the boilerplate object. 4955 // Push the boilerplate object.
4734 frame_->Push(&boilerplate); 4956 frame_->Push(&boilerplate);
4735 } 4957 }
4736 4958
4737 4959
4738 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 4960 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
4961 ASSERT(!in_safe_int32_mode());
4739 Comment cmnt(masm_, "[ ObjectLiteral"); 4962 Comment cmnt(masm_, "[ ObjectLiteral");
4740 4963
4741 // Load a writable copy of the function of this activation in a 4964 // Load a writable copy of the function of this activation in a
4742 // register. 4965 // register.
4743 frame_->PushFunction(); 4966 frame_->PushFunction();
4744 Result literals = frame_->Pop(); 4967 Result literals = frame_->Pop();
4745 literals.ToRegister(); 4968 literals.ToRegister();
4746 frame_->Spill(literals.reg()); 4969 frame_->Spill(literals.reg());
4747 4970
4748 // Load the literals array of the function. 4971 // Load the literals array of the function.
4749 __ mov(literals.reg(), 4972 __ mov(literals.reg(),
4750 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 4973 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
4751 // Literal array. 4974 // Literal array.
4752 frame_->Push(&literals); 4975 frame_->Push(&literals);
4753 // Literal index. 4976 // Literal index.
4754 frame_->Push(Smi::FromInt(node->literal_index())); 4977 frame_->Push(Smi::FromInt(node->literal_index()));
4755 // Constant properties. 4978 // Constant properties.
4756 frame_->Push(node->constant_properties()); 4979 frame_->Push(node->constant_properties());
4980 // Should the object literal have fast elements?
4981 frame_->Push(Smi::FromInt(node->fast_elements() ? 1 : 0));
4757 Result clone; 4982 Result clone;
4758 if (node->depth() > 1) { 4983 if (node->depth() > 1) {
4759 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); 4984 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 4);
4760 } else { 4985 } else {
4761 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); 4986 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
4762 } 4987 }
4763 frame_->Push(&clone); 4988 frame_->Push(&clone);
4764 4989
4765 for (int i = 0; i < node->properties()->length(); i++) { 4990 for (int i = 0; i < node->properties()->length(); i++) {
4766 ObjectLiteral::Property* property = node->properties()->at(i); 4991 ObjectLiteral::Property* property = node->properties()->at(i);
4767 switch (property->kind()) { 4992 switch (property->kind()) {
4768 case ObjectLiteral::Property::CONSTANT: 4993 case ObjectLiteral::Property::CONSTANT:
4769 break; 4994 break;
4770 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 4995 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
4771 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 4996 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4811 // Ignore the result. 5036 // Ignore the result.
4812 break; 5037 break;
4813 } 5038 }
4814 default: UNREACHABLE(); 5039 default: UNREACHABLE();
4815 } 5040 }
4816 } 5041 }
4817 } 5042 }
4818 5043
4819 5044
4820 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 5045 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
5046 ASSERT(!in_safe_int32_mode());
4821 Comment cmnt(masm_, "[ ArrayLiteral"); 5047 Comment cmnt(masm_, "[ ArrayLiteral");
4822 5048
4823 // Load a writable copy of the function of this activation in a 5049 // Load a writable copy of the function of this activation in a
4824 // register. 5050 // register.
4825 frame_->PushFunction(); 5051 frame_->PushFunction();
4826 Result literals = frame_->Pop(); 5052 Result literals = frame_->Pop();
4827 literals.ToRegister(); 5053 literals.ToRegister();
4828 frame_->Spill(literals.reg()); 5054 frame_->Spill(literals.reg());
4829 5055
4830 // Load the literals array of the function. 5056 // Load the literals array of the function.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4882 // Update the write barrier for the array address. 5108 // Update the write barrier for the array address.
4883 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier. 5109 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
4884 Result scratch = allocator_->Allocate(); 5110 Result scratch = allocator_->Allocate();
4885 ASSERT(scratch.is_valid()); 5111 ASSERT(scratch.is_valid());
4886 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg()); 5112 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
4887 } 5113 }
4888 } 5114 }
4889 5115
4890 5116
4891 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { 5117 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
5118 ASSERT(!in_safe_int32_mode());
4892 ASSERT(!in_spilled_code()); 5119 ASSERT(!in_spilled_code());
4893 // Call runtime routine to allocate the catch extension object and 5120 // Call runtime routine to allocate the catch extension object and
4894 // assign the exception value to the catch variable. 5121 // assign the exception value to the catch variable.
4895 Comment cmnt(masm_, "[ CatchExtensionObject"); 5122 Comment cmnt(masm_, "[ CatchExtensionObject");
4896 Load(node->key()); 5123 Load(node->key());
4897 Load(node->value()); 5124 Load(node->value());
4898 Result result = 5125 Result result =
4899 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 5126 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
4900 frame_->Push(&result); 5127 frame_->Push(&result);
4901 } 5128 }
(...skipping 13 matching lines...) Expand all
4915 if (node->is_compound()) { 5142 if (node->is_compound()) {
4916 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); 5143 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
4917 frame()->Push(&result); 5144 frame()->Push(&result);
4918 Load(node->value()); 5145 Load(node->value());
4919 5146
4920 bool overwrite_value = 5147 bool overwrite_value =
4921 (node->value()->AsBinaryOperation() != NULL && 5148 (node->value()->AsBinaryOperation() != NULL &&
4922 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 5149 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
4923 GenericBinaryOperation(node->binary_op(), 5150 GenericBinaryOperation(node->binary_op(),
4924 node->type(), 5151 node->type(),
4925 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 5152 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE,
5153 node->no_negative_zero());
4926 } else { 5154 } else {
4927 Load(node->value()); 5155 Load(node->value());
4928 } 5156 }
4929 5157
4930 // Perform the assignment. 5158 // Perform the assignment.
4931 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { 5159 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) {
4932 CodeForSourcePosition(node->position()); 5160 CodeForSourcePosition(node->position());
4933 StoreToSlot(slot, 5161 StoreToSlot(slot,
4934 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); 5162 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT);
4935 } 5163 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
4992 } 5220 }
4993 Result value = EmitNamedLoad(name, var != NULL); 5221 Result value = EmitNamedLoad(name, var != NULL);
4994 frame()->Push(&value); 5222 frame()->Push(&value);
4995 Load(node->value()); 5223 Load(node->value());
4996 5224
4997 bool overwrite_value = 5225 bool overwrite_value =
4998 (node->value()->AsBinaryOperation() != NULL && 5226 (node->value()->AsBinaryOperation() != NULL &&
4999 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 5227 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5000 GenericBinaryOperation(node->binary_op(), 5228 GenericBinaryOperation(node->binary_op(),
5001 node->type(), 5229 node->type(),
5002 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 5230 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE,
5231 node->no_negative_zero());
5003 } else { 5232 } else {
5004 Load(node->value()); 5233 Load(node->value());
5005 } 5234 }
5006 5235
5007 // Perform the assignment. It is safe to ignore constants here. 5236 // Perform the assignment. It is safe to ignore constants here.
5008 ASSERT(var == NULL || var->mode() != Variable::CONST); 5237 ASSERT(var == NULL || var->mode() != Variable::CONST);
5009 ASSERT_NE(Token::INIT_CONST, node->op()); 5238 ASSERT_NE(Token::INIT_CONST, node->op());
5010 if (is_trivial_receiver) { 5239 if (is_trivial_receiver) {
5011 Result value = frame()->Pop(); 5240 Result value = frame()->Pop();
5012 frame()->Push(prop->obj()); 5241 frame()->Push(prop->obj());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
5071 frame()->PushElementAt(1); 5300 frame()->PushElementAt(1);
5072 Result value = EmitKeyedLoad(); 5301 Result value = EmitKeyedLoad();
5073 frame()->Push(&value); 5302 frame()->Push(&value);
5074 Load(node->value()); 5303 Load(node->value());
5075 5304
5076 bool overwrite_value = 5305 bool overwrite_value =
5077 (node->value()->AsBinaryOperation() != NULL && 5306 (node->value()->AsBinaryOperation() != NULL &&
5078 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 5307 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5079 GenericBinaryOperation(node->binary_op(), 5308 GenericBinaryOperation(node->binary_op(),
5080 node->type(), 5309 node->type(),
5081 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 5310 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE,
5311 node->no_negative_zero());
5082 } else { 5312 } else {
5083 Load(node->value()); 5313 Load(node->value());
5084 } 5314 }
5085 5315
5086 // Perform the assignment. It is safe to ignore constants here. 5316 // Perform the assignment. It is safe to ignore constants here.
5087 ASSERT(node->op() != Token::INIT_CONST); 5317 ASSERT(node->op() != Token::INIT_CONST);
5088 CodeForSourcePosition(node->position()); 5318 CodeForSourcePosition(node->position());
5089 Result answer = EmitKeyedStore(prop->key()->type()); 5319 Result answer = EmitKeyedStore(prop->key()->type());
5090 frame()->Push(&answer); 5320 frame()->Push(&answer);
5091 5321
5092 if (node->ends_initialization_block()) { 5322 if (node->ends_initialization_block()) {
5093 // The argument to the runtime call is the extra copy of the receiver, 5323 // The argument to the runtime call is the extra copy of the receiver,
5094 // which is below the value of the assignment. Swap the receiver and 5324 // which is below the value of the assignment. Swap the receiver and
5095 // the value of the assignment expression. 5325 // the value of the assignment expression.
5096 Result result = frame()->Pop(); 5326 Result result = frame()->Pop();
5097 Result receiver = frame()->Pop(); 5327 Result receiver = frame()->Pop();
5098 frame()->Push(&result); 5328 frame()->Push(&result);
5099 frame()->Push(&receiver); 5329 frame()->Push(&receiver);
5100 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 5330 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5101 } 5331 }
5102 5332
5103 ASSERT(frame()->height() == original_height + 1); 5333 ASSERT(frame()->height() == original_height + 1);
5104 } 5334 }
5105 5335
5106 5336
5107 void CodeGenerator::VisitAssignment(Assignment* node) { 5337 void CodeGenerator::VisitAssignment(Assignment* node) {
5338 ASSERT(!in_safe_int32_mode());
5108 #ifdef DEBUG 5339 #ifdef DEBUG
5109 int original_height = frame()->height(); 5340 int original_height = frame()->height();
5110 #endif 5341 #endif
5111 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 5342 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5112 Property* prop = node->target()->AsProperty(); 5343 Property* prop = node->target()->AsProperty();
5113 5344
5114 if (var != NULL && !var->is_global()) { 5345 if (var != NULL && !var->is_global()) {
5115 EmitSlotAssignment(node); 5346 EmitSlotAssignment(node);
5116 5347
5117 } else if ((prop != NULL && prop->key()->IsPropertyName()) || 5348 } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
(...skipping 15 matching lines...) Expand all
5133 // The runtime call doesn't actually return but the code generator will 5364 // The runtime call doesn't actually return but the code generator will
5134 // still generate code and expects a certain frame height. 5365 // still generate code and expects a certain frame height.
5135 frame()->Push(&result); 5366 frame()->Push(&result);
5136 } 5367 }
5137 5368
5138 ASSERT(frame()->height() == original_height + 1); 5369 ASSERT(frame()->height() == original_height + 1);
5139 } 5370 }
5140 5371
5141 5372
5142 void CodeGenerator::VisitThrow(Throw* node) { 5373 void CodeGenerator::VisitThrow(Throw* node) {
5374 ASSERT(!in_safe_int32_mode());
5143 Comment cmnt(masm_, "[ Throw"); 5375 Comment cmnt(masm_, "[ Throw");
5144 Load(node->exception()); 5376 Load(node->exception());
5145 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 5377 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
5146 frame_->Push(&result); 5378 frame_->Push(&result);
5147 } 5379 }
5148 5380
5149 5381
5150 void CodeGenerator::VisitProperty(Property* node) { 5382 void CodeGenerator::VisitProperty(Property* node) {
5383 ASSERT(!in_safe_int32_mode());
5151 Comment cmnt(masm_, "[ Property"); 5384 Comment cmnt(masm_, "[ Property");
5152 Reference property(this, node); 5385 Reference property(this, node);
5153 property.GetValue(); 5386 property.GetValue();
5154 } 5387 }
5155 5388
5156 5389
5157 void CodeGenerator::VisitCall(Call* node) { 5390 void CodeGenerator::VisitCall(Call* node) {
5391 ASSERT(!in_safe_int32_mode());
5158 Comment cmnt(masm_, "[ Call"); 5392 Comment cmnt(masm_, "[ Call");
5159 5393
5160 Expression* function = node->expression(); 5394 Expression* function = node->expression();
5161 ZoneList<Expression*>* args = node->arguments(); 5395 ZoneList<Expression*>* args = node->arguments();
5162 5396
5163 // Check if the function is a variable or a property. 5397 // Check if the function is a variable or a property.
5164 Variable* var = function->AsVariableProxy()->AsVariable(); 5398 Variable* var = function->AsVariableProxy()->AsVariable();
5165 Property* property = function->AsProperty(); 5399 Property* property = function->AsProperty();
5166 5400
5167 // ------------------------------------------------------------------------ 5401 // ------------------------------------------------------------------------
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
5363 // Pass the global proxy as the receiver. 5597 // Pass the global proxy as the receiver.
5364 LoadGlobalReceiver(); 5598 LoadGlobalReceiver();
5365 5599
5366 // Call the function. 5600 // Call the function.
5367 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); 5601 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
5368 } 5602 }
5369 } 5603 }
5370 5604
5371 5605
5372 void CodeGenerator::VisitCallNew(CallNew* node) { 5606 void CodeGenerator::VisitCallNew(CallNew* node) {
5607 ASSERT(!in_safe_int32_mode());
5373 Comment cmnt(masm_, "[ CallNew"); 5608 Comment cmnt(masm_, "[ CallNew");
5374 5609
5375 // According to ECMA-262, section 11.2.2, page 44, the function 5610 // According to ECMA-262, section 11.2.2, page 44, the function
5376 // expression in new calls must be evaluated before the 5611 // expression in new calls must be evaluated before the
5377 // arguments. This is different from ordinary calls, where the 5612 // arguments. This is different from ordinary calls, where the
5378 // actual function to call is resolved after the arguments have been 5613 // actual function to call is resolved after the arguments have been
5379 // evaluated. 5614 // evaluated.
5380 5615
5381 // Compute function to call and use the global object as the 5616 // Compute function to call and use the global object as the
5382 // receiver. There is no need to use the global proxy here because 5617 // receiver. There is no need to use the global proxy here because
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
5905 object.Unuse(); 6140 object.Unuse();
5906 scratch.Unuse(); 6141 scratch.Unuse();
5907 duplicate_value.Unuse(); 6142 duplicate_value.Unuse();
5908 6143
5909 // Leave. 6144 // Leave.
5910 leave.Bind(&value); 6145 leave.Bind(&value);
5911 frame_->Push(&value); 6146 frame_->Push(&value);
5912 } 6147 }
5913 6148
5914 6149
5915 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 6150 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
5916 ASSERT(args->length() == 1); 6151 ASSERT(args->length() == 1);
5917 6152
5918 // ArgumentsAccessStub expects the key in edx and the formal 6153 // ArgumentsAccessStub expects the key in edx and the formal
5919 // parameter count in eax. 6154 // parameter count in eax.
5920 Load(args->at(0)); 6155 Load(args->at(0));
5921 Result key = frame_->Pop(); 6156 Result key = frame_->Pop();
5922 // Explicitly create a constant result. 6157 // Explicitly create a constant result.
5923 Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters()))); 6158 Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters())));
5924 // Call the shared stub to get to arguments[key]. 6159 // Call the shared stub to get to arguments[key].
5925 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 6160 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
6290 __ bind(&runtime); 6525 __ bind(&runtime);
6291 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1); 6526 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1);
6292 6527
6293 end.Bind(&result); 6528 end.Bind(&result);
6294 frame()->Push(&result); 6529 frame()->Push(&result);
6295 } 6530 }
6296 } 6531 }
6297 6532
6298 6533
6299 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 6534 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
6535 ASSERT(!in_safe_int32_mode());
6300 if (CheckForInlineRuntimeCall(node)) { 6536 if (CheckForInlineRuntimeCall(node)) {
6301 return; 6537 return;
6302 } 6538 }
6303 6539
6304 ZoneList<Expression*>* args = node->arguments(); 6540 ZoneList<Expression*>* args = node->arguments();
6305 Comment cmnt(masm_, "[ CallRuntime"); 6541 Comment cmnt(masm_, "[ CallRuntime");
6306 Runtime::Function* function = node->function(); 6542 Runtime::Function* function = node->function();
6307 6543
6308 if (function == NULL) { 6544 if (function == NULL) {
6309 // Push the builtins object found in the current global object. 6545 // Push the builtins object found in the current global object.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
6416 expression->AsLiteral()->IsNull())) { 6652 expression->AsLiteral()->IsNull())) {
6417 // Omit evaluating the value of the primitive literal. 6653 // Omit evaluating the value of the primitive literal.
6418 // It will be discarded anyway, and can have no side effect. 6654 // It will be discarded anyway, and can have no side effect.
6419 frame_->Push(Factory::undefined_value()); 6655 frame_->Push(Factory::undefined_value());
6420 } else { 6656 } else {
6421 Load(node->expression()); 6657 Load(node->expression());
6422 frame_->SetElementAt(0, Factory::undefined_value()); 6658 frame_->SetElementAt(0, Factory::undefined_value());
6423 } 6659 }
6424 6660
6425 } else { 6661 } else {
6426 Load(node->expression()); 6662 if (in_safe_int32_mode()) {
6427 bool overwrite = 6663 Visit(node->expression());
6428 (node->expression()->AsBinaryOperation() != NULL && 6664 Result value = frame_->Pop();
6429 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 6665 ASSERT(value.is_untagged_int32());
6430 switch (op) { 6666 // Registers containing an int32 value are not multiply used.
6431 case Token::SUB: { 6667 ASSERT(!value.is_register() || !frame_->is_used(value.reg()));
6432 GenericUnaryOpStub stub(Token::SUB, overwrite); 6668 value.ToRegister();
6433 Result operand = frame_->Pop(); 6669 switch (op) {
6434 Result answer = frame_->CallStub(&stub, &operand); 6670 case Token::SUB: {
6435 frame_->Push(&answer); 6671 __ neg(value.reg());
6436 break; 6672 if (node->no_negative_zero()) {
6673 // -MIN_INT is MIN_INT with the overflow flag set.
6674 unsafe_bailout_->Branch(overflow);
6675 } else {
6676 // MIN_INT and 0 both have bad negations. They both have 31 zeros.
6677 __ test(value.reg(), Immediate(0x7FFFFFFF));
6678 unsafe_bailout_->Branch(zero);
6679 }
6680 break;
6681 }
6682 case Token::BIT_NOT: {
6683 __ not_(value.reg());
6684 break;
6685 }
6686 case Token::ADD: {
6687 // Unary plus has no effect on int32 values.
6688 break;
6689 }
6690 default:
6691 UNREACHABLE();
6692 break;
6437 } 6693 }
6694 frame_->Push(&value);
6695 } else {
6696 Load(node->expression());
6697 bool overwrite =
6698 (node->expression()->AsBinaryOperation() != NULL &&
6699 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
6700 switch (op) {
6701 case Token::SUB: {
6702 GenericUnaryOpStub stub(Token::SUB, overwrite);
6703 Result operand = frame_->Pop();
6704 Result answer = frame_->CallStub(&stub, &operand);
6705 answer.set_number_info(NumberInfo::Number());
6706 frame_->Push(&answer);
6707 break;
6708 }
6709 case Token::BIT_NOT: {
6710 // Smi check.
6711 JumpTarget smi_label;
6712 JumpTarget continue_label;
6713 Result operand = frame_->Pop();
6714 NumberInfo operand_info = operand.number_info();
6715 operand.ToRegister();
6716 if (operand_info.IsSmi()) {
6717 if (FLAG_debug_code) __ AbortIfNotSmi(operand.reg());
6718 frame_->Spill(operand.reg());
6719 // Set smi tag bit. It will be reset by the not operation.
6720 __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask));
6721 __ not_(operand.reg());
6722 Result answer = operand;
6723 answer.set_number_info(NumberInfo::Smi());
6724 frame_->Push(&answer);
6725 } else {
6726 __ test(operand.reg(), Immediate(kSmiTagMask));
6727 smi_label.Branch(zero, &operand, taken);
6438 6728
6439 case Token::BIT_NOT: { 6729 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
6440 // Smi check. 6730 Result answer = frame_->CallStub(&stub, &operand);
6441 JumpTarget smi_label; 6731 continue_label.Jump(&answer);
6442 JumpTarget continue_label;
6443 Result operand = frame_->Pop();
6444 operand.ToRegister();
6445 __ test(operand.reg(), Immediate(kSmiTagMask));
6446 smi_label.Branch(zero, &operand, taken);
6447 6732
6448 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 6733 smi_label.Bind(&answer);
6449 Result answer = frame_->CallStub(&stub, &operand); 6734 answer.ToRegister();
6450 continue_label.Jump(&answer); 6735 frame_->Spill(answer.reg());
6736 // Set smi tag bit. It will be reset by the not operation.
6737 __ lea(answer.reg(), Operand(answer.reg(), kSmiTagMask));
6738 __ not_(answer.reg());
6451 6739
6452 smi_label.Bind(&answer); 6740 continue_label.Bind(&answer);
6453 answer.ToRegister(); 6741 if (operand_info.IsInteger32()) {
6454 frame_->Spill(answer.reg()); 6742 answer.set_number_info(NumberInfo::Integer32());
6455 __ not_(answer.reg()); 6743 } else {
6456 __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag. 6744 answer.set_number_info(NumberInfo::Number());
6745 }
6746 frame_->Push(&answer);
6747 }
6748 break;
6749 }
6750 case Token::ADD: {
6751 // Smi check.
6752 JumpTarget continue_label;
6753 Result operand = frame_->Pop();
6754 NumberInfo operand_info = operand.number_info();
6755 operand.ToRegister();
6756 __ test(operand.reg(), Immediate(kSmiTagMask));
6757 continue_label.Branch(zero, &operand, taken);
6457 6758
6458 continue_label.Bind(&answer); 6759 frame_->Push(&operand);
6459 frame_->Push(&answer); 6760 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER,
6460 break;
6461 }
6462
6463 case Token::ADD: {
6464 // Smi check.
6465 JumpTarget continue_label;
6466 Result operand = frame_->Pop();
6467 operand.ToRegister();
6468 __ test(operand.reg(), Immediate(kSmiTagMask));
6469 continue_label.Branch(zero, &operand, taken);
6470
6471 frame_->Push(&operand);
6472 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER,
6473 CALL_FUNCTION, 1); 6761 CALL_FUNCTION, 1);
6474 6762
6475 continue_label.Bind(&answer); 6763 continue_label.Bind(&answer);
6476 frame_->Push(&answer); 6764 if (operand_info.IsSmi()) {
6477 break; 6765 answer.set_number_info(NumberInfo::Smi());
6766 } else if (operand_info.IsInteger32()) {
6767 answer.set_number_info(NumberInfo::Integer32());
6768 } else {
6769 answer.set_number_info(NumberInfo::Number());
6770 }
6771 frame_->Push(&answer);
6772 break;
6773 }
6774 default:
6775 // NOT, DELETE, TYPEOF, and VOID are handled outside the
6776 // switch.
6777 UNREACHABLE();
6478 } 6778 }
6479
6480 default:
6481 // NOT, DELETE, TYPEOF, and VOID are handled outside the
6482 // switch.
6483 UNREACHABLE();
6484 } 6779 }
6485 } 6780 }
6486 } 6781 }
6487 6782
6488 6783
6489 // The value in dst was optimistically incremented or decremented. The 6784 // The value in dst was optimistically incremented or decremented. The
6490 // result overflowed or was not smi tagged. Undo the operation, call 6785 // result overflowed or was not smi tagged. Undo the operation, call
6491 // into the runtime to convert the argument to a number, and call the 6786 // into the runtime to convert the argument to a number, and call the
6492 // specialized add or subtract stub. The result is left in dst. 6787 // specialized add or subtract stub. The result is left in dst.
6493 class DeferredPrefixCountOperation: public DeferredCode { 6788 class DeferredPrefixCountOperation: public DeferredCode {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
6566 __ CallRuntime(Runtime::kNumberAdd, 2); 6861 __ CallRuntime(Runtime::kNumberAdd, 2);
6567 } else { 6862 } else {
6568 __ CallRuntime(Runtime::kNumberSub, 2); 6863 __ CallRuntime(Runtime::kNumberSub, 2);
6569 } 6864 }
6570 if (!dst_.is(eax)) __ mov(dst_, eax); 6865 if (!dst_.is(eax)) __ mov(dst_, eax);
6571 __ pop(old_); 6866 __ pop(old_);
6572 } 6867 }
6573 6868
6574 6869
6575 void CodeGenerator::VisitCountOperation(CountOperation* node) { 6870 void CodeGenerator::VisitCountOperation(CountOperation* node) {
6871 ASSERT(!in_safe_int32_mode());
6576 Comment cmnt(masm_, "[ CountOperation"); 6872 Comment cmnt(masm_, "[ CountOperation");
6577 6873
6578 bool is_postfix = node->is_postfix(); 6874 bool is_postfix = node->is_postfix();
6579 bool is_increment = node->op() == Token::INC; 6875 bool is_increment = node->op() == Token::INC;
6580 6876
6581 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 6877 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
6582 bool is_const = (var != NULL && var->mode() == Variable::CONST); 6878 bool is_const = (var != NULL && var->mode() == Variable::CONST);
6583 6879
6584 // Postfix operations need a stack slot under the reference to hold 6880 // Postfix operations need a stack slot under the reference to hold
6585 // the old value while the new value is being stored. This is so that 6881 // the old value while the new value is being stored. This is so that
(...skipping 14 matching lines...) Expand all
6600 6896
6601 Result new_value = frame_->Pop(); 6897 Result new_value = frame_->Pop();
6602 new_value.ToRegister(); 6898 new_value.ToRegister();
6603 6899
6604 Result old_value; // Only allocated in the postfix case. 6900 Result old_value; // Only allocated in the postfix case.
6605 if (is_postfix) { 6901 if (is_postfix) {
6606 // Allocate a temporary to preserve the old value. 6902 // Allocate a temporary to preserve the old value.
6607 old_value = allocator_->Allocate(); 6903 old_value = allocator_->Allocate();
6608 ASSERT(old_value.is_valid()); 6904 ASSERT(old_value.is_valid());
6609 __ mov(old_value.reg(), new_value.reg()); 6905 __ mov(old_value.reg(), new_value.reg());
6906
6907 // The return value for postfix operations is the
6908 // same as the input, and has the same number info.
6909 old_value.set_number_info(new_value.number_info());
6610 } 6910 }
6911
6611 // Ensure the new value is writable. 6912 // Ensure the new value is writable.
6612 frame_->Spill(new_value.reg()); 6913 frame_->Spill(new_value.reg());
6613 6914
6614 // In order to combine the overflow and the smi tag check, we need 6915 Result tmp;
6615 // to be able to allocate a byte register. We attempt to do so 6916 if (new_value.is_smi()) {
6616 // without spilling. If we fail, we will generate separate overflow 6917 if (FLAG_debug_code) __ AbortIfNotSmi(new_value.reg());
6617 // and smi tag checks. 6918 } else {
6618 // 6919 // We don't know statically if the input is a smi.
6619 // We allocate and clear the temporary byte register before 6920 // In order to combine the overflow and the smi tag check, we need
6620 // performing the count operation since clearing the register using 6921 // to be able to allocate a byte register. We attempt to do so
6621 // xor will clear the overflow flag. 6922 // without spilling. If we fail, we will generate separate overflow
6622 Result tmp = allocator_->AllocateByteRegisterWithoutSpilling(); 6923 // and smi tag checks.
6623 if (tmp.is_valid()) { 6924 // We allocate and clear a temporary byte register before performing
6624 __ Set(tmp.reg(), Immediate(0)); 6925 // the count operation since clearing the register using xor will clear
6926 // the overflow flag.
6927 tmp = allocator_->AllocateByteRegisterWithoutSpilling();
6928 if (tmp.is_valid()) {
6929 __ Set(tmp.reg(), Immediate(0));
6930 }
6931 }
6932
6933 if (is_increment) {
6934 __ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
6935 } else {
6936 __ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
6625 } 6937 }
6626 6938
6627 DeferredCode* deferred = NULL; 6939 DeferredCode* deferred = NULL;
6628 if (is_postfix) { 6940 if (is_postfix) {
6629 deferred = new DeferredPostfixCountOperation(new_value.reg(), 6941 deferred = new DeferredPostfixCountOperation(new_value.reg(),
6630 old_value.reg(), 6942 old_value.reg(),
6631 is_increment); 6943 is_increment);
6632 } else { 6944 } else {
6633 deferred = new DeferredPrefixCountOperation(new_value.reg(), 6945 deferred = new DeferredPrefixCountOperation(new_value.reg(),
6634 is_increment); 6946 is_increment);
6635 } 6947 }
6636 6948
6637 if (is_increment) { 6949 if (new_value.is_smi()) {
6638 __ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); 6950 // In case we have a smi as input just check for overflow.
6951 deferred->Branch(overflow);
6639 } else { 6952 } else {
6640 __ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); 6953 // If the count operation didn't overflow and the result is a valid
6641 } 6954 // smi, we're done. Otherwise, we jump to the deferred slow-case
6642 6955 // code.
6643 // If the count operation didn't overflow and the result is a valid
6644 // smi, we're done. Otherwise, we jump to the deferred slow-case
6645 // code.
6646 if (tmp.is_valid()) {
6647 // We combine the overflow and the smi tag check if we could 6956 // We combine the overflow and the smi tag check if we could
6648 // successfully allocate a temporary byte register. 6957 // successfully allocate a temporary byte register.
6649 __ setcc(overflow, tmp.reg()); 6958 if (tmp.is_valid()) {
6650 __ or_(Operand(tmp.reg()), new_value.reg()); 6959 __ setcc(overflow, tmp.reg());
6651 __ test(tmp.reg(), Immediate(kSmiTagMask)); 6960 __ or_(Operand(tmp.reg()), new_value.reg());
6652 tmp.Unuse(); 6961 __ test(tmp.reg(), Immediate(kSmiTagMask));
6653 deferred->Branch(not_zero); 6962 tmp.Unuse();
6654 } else { 6963 deferred->Branch(not_zero);
6655 // Otherwise we test separately for overflow and smi tag. 6964 } else {
6656 deferred->Branch(overflow); 6965 // Otherwise we test separately for overflow and smi tag.
6657 __ test(new_value.reg(), Immediate(kSmiTagMask)); 6966 deferred->Branch(overflow);
6658 deferred->Branch(not_zero); 6967 __ test(new_value.reg(), Immediate(kSmiTagMask));
6968 deferred->Branch(not_zero);
6969 }
6659 } 6970 }
6660 deferred->BindExit(); 6971 deferred->BindExit();
6661 6972
6973 // The result of ++ or -- is an Integer32 if the
6974 // input is a smi. Otherwise it is a number.
6975 if (new_value.is_smi()) {
6976 new_value.set_number_info(NumberInfo::Integer32());
6977 } else {
6978 new_value.set_number_info(NumberInfo::Number());
6979 }
6980
6662 // Postfix: store the old value in the allocated slot under the 6981 // Postfix: store the old value in the allocated slot under the
6663 // reference. 6982 // reference.
6664 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); 6983 if (is_postfix) frame_->SetElementAt(target.size(), &old_value);
6665 6984
6666 frame_->Push(&new_value); 6985 frame_->Push(&new_value);
6667 // Non-constant: update the reference. 6986 // Non-constant: update the reference.
6668 if (!is_const) target.SetValue(NOT_CONST_INIT); 6987 if (!is_const) target.SetValue(NOT_CONST_INIT);
6669 } 6988 }
6670 6989
6671 // Postfix: drop the new value and use the old. 6990 // Postfix: drop the new value and use the old.
6672 if (is_postfix) frame_->Drop(); 6991 if (is_postfix) frame_->Drop();
6673 } 6992 }
6674 6993
6675 6994
6995 void CodeGenerator::Int32BinaryOperation(BinaryOperation* node) {
6996 Token::Value op = node->op();
6997 Comment cmnt(masm_, "[ Int32BinaryOperation");
6998 ASSERT(in_safe_int32_mode());
6999 ASSERT(safe_int32_mode_enabled());
7000 ASSERT(FLAG_safe_int32_compiler);
7001
7002 if (op == Token::COMMA) {
7003 // Discard left value.
7004 frame_->Nip(1);
7005 return;
7006 }
7007
7008 Result right = frame_->Pop();
7009 Result left = frame_->Pop();
7010
7011 ASSERT(right.is_untagged_int32());
7012 ASSERT(left.is_untagged_int32());
7013 // Registers containing an int32 value are not multiply used.
7014 ASSERT(!left.is_register() || !frame_->is_used(left.reg()));
7015 ASSERT(!right.is_register() || !frame_->is_used(right.reg()));
7016
7017 switch (op) {
7018 case Token::COMMA:
7019 case Token::OR:
7020 case Token::AND:
7021 UNREACHABLE();
7022 break;
7023 case Token::BIT_OR:
7024 case Token::BIT_XOR:
7025 case Token::BIT_AND:
7026 left.ToRegister();
7027 right.ToRegister();
7028 if (op == Token::BIT_OR) {
7029 __ or_(left.reg(), Operand(right.reg()));
7030 } else if (op == Token::BIT_XOR) {
7031 __ xor_(left.reg(), Operand(right.reg()));
7032 } else {
7033 ASSERT(op == Token::BIT_AND);
7034 __ and_(left.reg(), Operand(right.reg()));
7035 }
7036 frame_->Push(&left);
7037 right.Unuse();
7038 break;
7039 case Token::SAR:
7040 case Token::SHL:
7041 case Token::SHR: {
7042 bool test_shr_overflow = false;
7043 left.ToRegister();
7044 if (right.is_constant()) {
7045 ASSERT(right.handle()->IsSmi() || right.handle()->IsHeapNumber());
7046 int shift_amount = NumberToInt32(*right.handle()) & 0x1F;
7047 if (op == Token::SAR) {
7048 __ sar(left.reg(), shift_amount);
7049 } else if (op == Token::SHL) {
7050 __ shl(left.reg(), shift_amount);
7051 } else {
7052 ASSERT(op == Token::SHR);
7053 __ shr(left.reg(), shift_amount);
7054 if (shift_amount == 0) test_shr_overflow = true;
7055 }
7056 } else {
7057 // Move right to ecx
7058 if (left.is_register() && left.reg().is(ecx)) {
7059 right.ToRegister();
7060 __ xchg(left.reg(), right.reg());
7061 left = right; // Left is unused here, copy of right unused by Push.
7062 } else {
7063 right.ToRegister(ecx);
7064 left.ToRegister();
7065 }
7066 if (op == Token::SAR) {
7067 __ sar_cl(left.reg());
7068 } else if (op == Token::SHL) {
7069 __ shl_cl(left.reg());
7070 } else {
7071 ASSERT(op == Token::SHR);
7072 __ shr_cl(left.reg());
7073 test_shr_overflow = true;
7074 }
7075 }
7076 {
7077 Register left_reg = left.reg();
7078 frame_->Push(&left);
7079 right.Unuse();
7080 if (test_shr_overflow && !node->to_int32()) {
7081 // Uint32 results with top bit set are not Int32 values.
7082 // If they will be forced to Int32, skip the test.
7083 // Test is needed because shr with shift amount 0 does not set flags.
7084 __ test(left_reg, Operand(left_reg));
7085 unsafe_bailout_->Branch(sign);
7086 }
7087 }
7088 break;
7089 }
7090 case Token::ADD:
7091 case Token::SUB:
7092 case Token::MUL:
7093 left.ToRegister();
7094 right.ToRegister();
7095 if (op == Token::ADD) {
7096 __ add(left.reg(), Operand(right.reg()));
7097 } else if (op == Token::SUB) {
7098 __ sub(left.reg(), Operand(right.reg()));
7099 } else {
7100 ASSERT(op == Token::MUL);
7101 // We have statically verified that a negative zero can be ignored.
7102 __ imul(left.reg(), Operand(right.reg()));
7103 }
7104 right.Unuse();
7105 frame_->Push(&left);
7106 if (!node->to_int32()) {
7107 // If ToInt32 is called on the result of ADD, SUB, or MUL, we don't
7108 // care about overflows.
7109 unsafe_bailout_->Branch(overflow);
7110 }
7111 break;
7112 case Token::DIV:
7113 case Token::MOD: {
7114 if (right.is_register() && (right.reg().is(eax) || right.reg().is(edx))) {
7115 if (left.is_register() && left.reg().is(edi)) {
7116 right.ToRegister(ebx);
7117 } else {
7118 right.ToRegister(edi);
7119 }
7120 }
7121 left.ToRegister(eax);
7122 Result edx_reg = allocator_->Allocate(edx);
7123 right.ToRegister();
7124 // The results are unused here because BreakTarget::Branch cannot handle
7125 // live results.
7126 Register right_reg = right.reg();
7127 left.Unuse();
7128 right.Unuse();
7129 edx_reg.Unuse();
7130 __ cmp(right_reg, 0);
7131 // Ensure divisor is positive: no chance of non-int32 or -0 result.
7132 unsafe_bailout_->Branch(less_equal);
7133 __ cdq(); // Sign-extend eax into edx:eax
7134 __ idiv(right_reg);
7135 if (op == Token::MOD) {
7136 Result edx_result(edx, NumberInfo::Integer32());
7137 edx_result.set_untagged_int32(true);
7138 frame_->Push(&edx_result);
7139 } else {
7140 ASSERT(op == Token::DIV);
7141 __ test(edx, Operand(edx));
7142 unsafe_bailout_->Branch(not_equal);
7143 Result eax_result(eax, NumberInfo::Integer32());
7144 eax_result.set_untagged_int32(true);
7145 frame_->Push(&eax_result);
7146 }
7147 break;
7148 }
7149 default:
7150 UNREACHABLE();
7151 break;
7152 }
7153 }
7154
6676 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 7155 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
6677 Comment cmnt(masm_, "[ BinaryOperation"); 7156 Comment cmnt(masm_, "[ BinaryOperation");
6678 Token::Value op = node->op(); 7157 Token::Value op = node->op();
6679 7158
6680 // According to ECMA-262 section 11.11, page 58, the binary logical 7159 // According to ECMA-262 section 11.11, page 58, the binary logical
6681 // operators must yield the result of one of the two expressions 7160 // operators must yield the result of one of the two expressions
6682 // before any ToBoolean() conversions. This means that the value 7161 // before any ToBoolean() conversions. This means that the value
6683 // produced by a && or || operator is not necessarily a boolean. 7162 // produced by a && or || operator is not necessarily a boolean.
6684 7163
6685 // NOTE: If the left hand side produces a materialized value (not 7164 // NOTE: If the left hand side produces a materialized value (not
6686 // control flow), we force the right hand side to do the same. This 7165 // control flow), we force the right hand side to do the same. This
6687 // is necessary because we assume that if we get control flow on the 7166 // is necessary because we assume that if we get control flow on the
6688 // last path out of an expression we got it on all paths. 7167 // last path out of an expression we got it on all paths.
6689 if (op == Token::AND) { 7168 if (op == Token::AND) {
7169 ASSERT(!in_safe_int32_mode());
6690 JumpTarget is_true; 7170 JumpTarget is_true;
6691 ControlDestination dest(&is_true, destination()->false_target(), true); 7171 ControlDestination dest(&is_true, destination()->false_target(), true);
6692 LoadCondition(node->left(), &dest, false); 7172 LoadCondition(node->left(), &dest, false);
6693 7173
6694 if (dest.false_was_fall_through()) { 7174 if (dest.false_was_fall_through()) {
6695 // The current false target was used as the fall-through. If 7175 // The current false target was used as the fall-through. If
6696 // there are no dangling jumps to is_true then the left 7176 // there are no dangling jumps to is_true then the left
6697 // subexpression was unconditionally false. Otherwise we have 7177 // subexpression was unconditionally false. Otherwise we have
6698 // paths where we do have to evaluate the right subexpression. 7178 // paths where we do have to evaluate the right subexpression.
6699 if (is_true.is_linked()) { 7179 if (is_true.is_linked()) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6743 7223
6744 // Compile right side expression. 7224 // Compile right side expression.
6745 is_true.Bind(); 7225 is_true.Bind();
6746 Load(node->right()); 7226 Load(node->right());
6747 7227
6748 // Exit (always with a materialized value). 7228 // Exit (always with a materialized value).
6749 exit.Bind(); 7229 exit.Bind();
6750 } 7230 }
6751 7231
6752 } else if (op == Token::OR) { 7232 } else if (op == Token::OR) {
7233 ASSERT(!in_safe_int32_mode());
6753 JumpTarget is_false; 7234 JumpTarget is_false;
6754 ControlDestination dest(destination()->true_target(), &is_false, false); 7235 ControlDestination dest(destination()->true_target(), &is_false, false);
6755 LoadCondition(node->left(), &dest, false); 7236 LoadCondition(node->left(), &dest, false);
6756 7237
6757 if (dest.true_was_fall_through()) { 7238 if (dest.true_was_fall_through()) {
6758 // The current true target was used as the fall-through. If 7239 // The current true target was used as the fall-through. If
6759 // there are no dangling jumps to is_false then the left 7240 // there are no dangling jumps to is_false then the left
6760 // subexpression was unconditionally true. Otherwise we have 7241 // subexpression was unconditionally true. Otherwise we have
6761 // paths where we do have to evaluate the right subexpression. 7242 // paths where we do have to evaluate the right subexpression.
6762 if (is_false.is_linked()) { 7243 if (is_false.is_linked()) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
6804 frame_->Drop(); 7285 frame_->Drop();
6805 7286
6806 // Compile right side expression. 7287 // Compile right side expression.
6807 is_false.Bind(); 7288 is_false.Bind();
6808 Load(node->right()); 7289 Load(node->right());
6809 7290
6810 // Exit (always with a materialized value). 7291 // Exit (always with a materialized value).
6811 exit.Bind(); 7292 exit.Bind();
6812 } 7293 }
6813 7294
7295 } else if (in_safe_int32_mode()) {
7296 Visit(node->left());
7297 Visit(node->right());
7298 Int32BinaryOperation(node);
6814 } else { 7299 } else {
6815 // NOTE: The code below assumes that the slow cases (calls to runtime) 7300 // NOTE: The code below assumes that the slow cases (calls to runtime)
6816 // never return a constant/immutable object. 7301 // never return a constant/immutable object.
6817 OverwriteMode overwrite_mode = NO_OVERWRITE; 7302 OverwriteMode overwrite_mode = NO_OVERWRITE;
6818 if (node->left()->AsBinaryOperation() != NULL && 7303 if (node->left()->AsBinaryOperation() != NULL &&
6819 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) { 7304 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
6820 overwrite_mode = OVERWRITE_LEFT; 7305 overwrite_mode = OVERWRITE_LEFT;
6821 } else if (node->right()->AsBinaryOperation() != NULL && 7306 } else if (node->right()->AsBinaryOperation() != NULL &&
6822 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) { 7307 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
6823 overwrite_mode = OVERWRITE_RIGHT; 7308 overwrite_mode = OVERWRITE_RIGHT;
6824 } 7309 }
6825 7310
6826 Load(node->left()); 7311 if (node->left()->IsTrivial()) {
6827 Load(node->right()); 7312 Load(node->right());
6828 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); 7313 Result right = frame_->Pop();
7314 frame_->Push(node->left());
7315 frame_->Push(&right);
7316 } else {
7317 Load(node->left());
7318 Load(node->right());
7319 }
7320 GenericBinaryOperation(node->op(), node->type(),
7321 overwrite_mode, node->no_negative_zero());
6829 } 7322 }
6830 } 7323 }
6831 7324
6832 7325
6833 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 7326 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
7327 ASSERT(!in_safe_int32_mode());
6834 frame_->PushFunction(); 7328 frame_->PushFunction();
6835 } 7329 }
6836 7330
6837 7331
6838 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 7332 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
7333 ASSERT(!in_safe_int32_mode());
6839 Comment cmnt(masm_, "[ CompareOperation"); 7334 Comment cmnt(masm_, "[ CompareOperation");
6840 7335
6841 bool left_already_loaded = false; 7336 bool left_already_loaded = false;
6842 7337
6843 // Get the expressions from the node. 7338 // Get the expressions from the node.
6844 Expression* left = node->left(); 7339 Expression* left = node->left();
6845 Expression* right = node->right(); 7340 Expression* right = node->right();
6846 Token::Value op = node->op(); 7341 Token::Value op = node->op();
6847 // To make typeof testing for natives implemented in JavaScript really 7342 // To make typeof testing for natives implemented in JavaScript really
6848 // efficient, we generate special code for expressions of the form: 7343 // efficient, we generate special code for expressions of the form:
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
7017 Result answer = frame_->CallStub(&stub, 2); 7512 Result answer = frame_->CallStub(&stub, 2);
7018 answer.ToRegister(); 7513 answer.ToRegister();
7019 __ test(answer.reg(), Operand(answer.reg())); 7514 __ test(answer.reg(), Operand(answer.reg()));
7020 answer.Unuse(); 7515 answer.Unuse();
7021 destination()->Split(zero); 7516 destination()->Split(zero);
7022 return; 7517 return;
7023 } 7518 }
7024 default: 7519 default:
7025 UNREACHABLE(); 7520 UNREACHABLE();
7026 } 7521 }
7027 if (!left_already_loaded) Load(left); 7522
7028 Load(right); 7523 if (left->IsTrivial()) {
7524 if (!left_already_loaded) {
7525 Load(right);
7526 Result right_result = frame_->Pop();
7527 frame_->Push(left);
7528 frame_->Push(&right_result);
7529 } else {
7530 Load(right);
7531 }
7532 } else {
7533 if (!left_already_loaded) Load(left);
7534 Load(right);
7535 }
7029 Comparison(node, cc, strict, destination()); 7536 Comparison(node, cc, strict, destination());
7030 } 7537 }
7031 7538
7032 7539
7033 #ifdef DEBUG 7540 #ifdef DEBUG
7034 bool CodeGenerator::HasValidEntryRegisters() { 7541 bool CodeGenerator::HasValidEntryRegisters() {
7035 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) 7542 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0))
7036 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) 7543 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
7037 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) 7544 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
7038 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) 7545 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
7364 // Use masm-> here instead of the double underscore macro since extra 7871 // Use masm-> here instead of the double underscore macro since extra
7365 // coverage code can interfere with the patching. 7872 // coverage code can interfere with the patching.
7366 masm_->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 7873 masm_->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
7367 Immediate(Factory::null_value())); 7874 Immediate(Factory::null_value()));
7368 deferred->Branch(not_equal); 7875 deferred->Branch(not_equal);
7369 7876
7370 // Check that the key is a smi. 7877 // Check that the key is a smi.
7371 if (!key.is_smi()) { 7878 if (!key.is_smi()) {
7372 __ test(key.reg(), Immediate(kSmiTagMask)); 7879 __ test(key.reg(), Immediate(kSmiTagMask));
7373 deferred->Branch(not_zero); 7880 deferred->Branch(not_zero);
7881 } else {
7882 if (FLAG_debug_code) __ AbortIfNotSmi(key.reg());
7374 } 7883 }
7375 7884
7376 // Get the elements array from the receiver and check that it 7885 // Get the elements array from the receiver and check that it
7377 // is not a dictionary. 7886 // is not a dictionary.
7378 __ mov(elements.reg(), 7887 __ mov(elements.reg(),
7379 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); 7888 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
7380 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), 7889 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
7381 Immediate(Factory::fixed_array_map())); 7890 Immediate(Factory::fixed_array_map()));
7382 deferred->Branch(not_equal); 7891 deferred->Branch(not_equal);
7383 7892
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
7517 8026
7518 8027
7519 static void CheckTwoForSminess(MacroAssembler* masm, 8028 static void CheckTwoForSminess(MacroAssembler* masm,
7520 Register left, Register right, Register scratch, 8029 Register left, Register right, Register scratch,
7521 NumberInfo left_info, NumberInfo right_info, 8030 NumberInfo left_info, NumberInfo right_info,
7522 DeferredInlineBinaryOperation* deferred) { 8031 DeferredInlineBinaryOperation* deferred) {
7523 if (left.is(right)) { 8032 if (left.is(right)) {
7524 if (!left_info.IsSmi()) { 8033 if (!left_info.IsSmi()) {
7525 __ test(left, Immediate(kSmiTagMask)); 8034 __ test(left, Immediate(kSmiTagMask));
7526 deferred->Branch(not_zero); 8035 deferred->Branch(not_zero);
8036 } else {
8037 if (FLAG_debug_code) __ AbortIfNotSmi(left);
7527 } 8038 }
7528 } else if (!left_info.IsSmi()) { 8039 } else if (!left_info.IsSmi()) {
7529 if (!right_info.IsSmi()) { 8040 if (!right_info.IsSmi()) {
7530 __ mov(scratch, left); 8041 __ mov(scratch, left);
7531 __ or_(scratch, Operand(right)); 8042 __ or_(scratch, Operand(right));
7532 __ test(scratch, Immediate(kSmiTagMask)); 8043 __ test(scratch, Immediate(kSmiTagMask));
7533 deferred->Branch(not_zero); 8044 deferred->Branch(not_zero);
7534 } else { 8045 } else {
7535 __ test(left, Immediate(kSmiTagMask)); 8046 __ test(left, Immediate(kSmiTagMask));
7536 deferred->Branch(not_zero); 8047 deferred->Branch(not_zero);
8048 if (FLAG_debug_code) __ AbortIfNotSmi(right);
7537 } 8049 }
7538 } else { 8050 } else {
8051 if (FLAG_debug_code) __ AbortIfNotSmi(left);
7539 if (!right_info.IsSmi()) { 8052 if (!right_info.IsSmi()) {
7540 __ test(right, Immediate(kSmiTagMask)); 8053 __ test(right, Immediate(kSmiTagMask));
7541 deferred->Branch(not_zero); 8054 deferred->Branch(not_zero);
8055 } else {
8056 if (FLAG_debug_code) __ AbortIfNotSmi(right);
7542 } 8057 }
7543 } 8058 }
7544 } 8059 }
7545 8060
7546 8061
7547 Handle<String> Reference::GetName() { 8062 Handle<String> Reference::GetName() {
7548 ASSERT(type_ == NAMED); 8063 ASSERT(type_ == NAMED);
7549 Property* property = expression_->AsProperty(); 8064 Property* property = expression_->AsProperty();
7550 if (property == NULL) { 8065 if (property == NULL) {
7551 // Global variable reference treated as a named property reference. 8066 // Global variable reference treated as a named property reference.
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
8038 __ mov(ebx, eax); 8553 __ mov(ebx, eax);
8039 __ mov(eax, edx); 8554 __ mov(eax, edx);
8040 } 8555 }
8041 } 8556 }
8042 if (!HasArgsInRegisters()) { 8557 if (!HasArgsInRegisters()) {
8043 __ mov(right, Operand(esp, 1 * kPointerSize)); 8558 __ mov(right, Operand(esp, 1 * kPointerSize));
8044 __ mov(left, Operand(esp, 2 * kPointerSize)); 8559 __ mov(left, Operand(esp, 2 * kPointerSize));
8045 } 8560 }
8046 8561
8047 if (static_operands_type_.IsSmi()) { 8562 if (static_operands_type_.IsSmi()) {
8563 if (FLAG_debug_code) {
8564 __ AbortIfNotSmi(left);
8565 __ AbortIfNotSmi(right);
8566 }
8048 if (op_ == Token::BIT_OR) { 8567 if (op_ == Token::BIT_OR) {
8049 __ or_(right, Operand(left)); 8568 __ or_(right, Operand(left));
8050 GenerateReturn(masm); 8569 GenerateReturn(masm);
8051 return; 8570 return;
8052 } else if (op_ == Token::BIT_AND) { 8571 } else if (op_ == Token::BIT_AND) {
8053 __ and_(right, Operand(left)); 8572 __ and_(right, Operand(left));
8054 GenerateReturn(masm); 8573 GenerateReturn(masm);
8055 return; 8574 return;
8056 } else if (op_ == Token::BIT_XOR) { 8575 } else if (op_ == Token::BIT_XOR) {
8057 __ xor_(right, Operand(left)); 8576 __ xor_(right, Operand(left));
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
8392 // forever for all other operations (also if smi code is skipped). 8911 // forever for all other operations (also if smi code is skipped).
8393 GenerateTypeTransition(masm); 8912 GenerateTypeTransition(masm);
8394 } 8913 }
8395 8914
8396 Label not_floats; 8915 Label not_floats;
8397 if (CpuFeatures::IsSupported(SSE2)) { 8916 if (CpuFeatures::IsSupported(SSE2)) {
8398 CpuFeatures::Scope use_sse2(SSE2); 8917 CpuFeatures::Scope use_sse2(SSE2);
8399 if (static_operands_type_.IsNumber()) { 8918 if (static_operands_type_.IsNumber()) {
8400 if (FLAG_debug_code) { 8919 if (FLAG_debug_code) {
8401 // Assert at runtime that inputs are only numbers. 8920 // Assert at runtime that inputs are only numbers.
8402 __ AbortIfNotNumber(edx, 8921 __ AbortIfNotNumber(edx);
8403 "GenericBinaryOpStub operand not a number."); 8922 __ AbortIfNotNumber(eax);
8404 __ AbortIfNotNumber(eax,
8405 "GenericBinaryOpStub operand not a number.");
8406 } 8923 }
8407 if (static_operands_type_.IsSmi()) { 8924 if (static_operands_type_.IsSmi()) {
8925 if (FLAG_debug_code) {
8926 __ AbortIfNotSmi(edx);
8927 __ AbortIfNotSmi(eax);
8928 }
8408 FloatingPointHelper::LoadSSE2Smis(masm, ecx); 8929 FloatingPointHelper::LoadSSE2Smis(masm, ecx);
8409 } else { 8930 } else {
8410 FloatingPointHelper::LoadSSE2Operands(masm); 8931 FloatingPointHelper::LoadSSE2Operands(masm);
8411 } 8932 }
8412 } else { 8933 } else {
8413 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime); 8934 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
8414 } 8935 }
8415 8936
8416 switch (op_) { 8937 switch (op_) {
8417 case Token::ADD: __ addsd(xmm0, xmm1); break; 8938 case Token::ADD: __ addsd(xmm0, xmm1); break;
8418 case Token::SUB: __ subsd(xmm0, xmm1); break; 8939 case Token::SUB: __ subsd(xmm0, xmm1); break;
8419 case Token::MUL: __ mulsd(xmm0, xmm1); break; 8940 case Token::MUL: __ mulsd(xmm0, xmm1); break;
8420 case Token::DIV: __ divsd(xmm0, xmm1); break; 8941 case Token::DIV: __ divsd(xmm0, xmm1); break;
8421 default: UNREACHABLE(); 8942 default: UNREACHABLE();
8422 } 8943 }
8423 GenerateHeapResultAllocation(masm, &call_runtime); 8944 GenerateHeapResultAllocation(masm, &call_runtime);
8424 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 8945 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
8425 GenerateReturn(masm); 8946 GenerateReturn(masm);
8426 } else { // SSE2 not available, use FPU. 8947 } else { // SSE2 not available, use FPU.
8427 if (static_operands_type_.IsNumber()) { 8948 if (static_operands_type_.IsNumber()) {
8428 if (FLAG_debug_code) { 8949 if (FLAG_debug_code) {
8429 // Assert at runtime that inputs are only numbers. 8950 // Assert at runtime that inputs are only numbers.
8430 __ AbortIfNotNumber(edx, 8951 __ AbortIfNotNumber(edx);
8431 "GenericBinaryOpStub operand not a number."); 8952 __ AbortIfNotNumber(eax);
8432 __ AbortIfNotNumber(eax,
8433 "GenericBinaryOpStub operand not a number.");
8434 } 8953 }
8435 } else { 8954 } else {
8436 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 8955 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
8437 } 8956 }
8438 FloatingPointHelper::LoadFloatOperands( 8957 FloatingPointHelper::LoadFloatOperands(
8439 masm, 8958 masm,
8440 ecx, 8959 ecx,
8441 FloatingPointHelper::ARGS_IN_REGISTERS); 8960 FloatingPointHelper::ARGS_IN_REGISTERS);
8442 switch (op_) { 8961 switch (op_) {
8443 case Token::ADD: __ faddp(1); break; 8962 case Token::ADD: __ faddp(1); break;
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
8785 __ TailCallExternalReference( 9304 __ TailCallExternalReference(
8786 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)), 9305 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
8787 6, 9306 6,
8788 1); 9307 1);
8789 9308
8790 // The entry point for the result calculation is assumed to be immediately 9309 // The entry point for the result calculation is assumed to be immediately
8791 // after this sequence. 9310 // after this sequence.
8792 __ bind(&get_result); 9311 __ bind(&get_result);
8793 } 9312 }
8794 9313
9314
8795 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { 9315 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
8796 GenericBinaryOpStub stub(key, type_info); 9316 GenericBinaryOpStub stub(key, type_info);
8797 HandleScope scope;
8798 return stub.GetCode(); 9317 return stub.GetCode();
8799 } 9318 }
8800 9319
8801 9320
8802 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 9321 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
8803 // Input on stack: 9322 // Input on stack:
8804 // esp[4]: argument (should be number). 9323 // esp[4]: argument (should be number).
8805 // esp[0]: return address. 9324 // esp[0]: return address.
8806 // Test that eax is a number. 9325 // Test that eax is a number.
8807 Label runtime_call; 9326 Label runtime_call;
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
9153 Label* conversion_failure) { 9672 Label* conversion_failure) {
9154 // Check float operands. 9673 // Check float operands.
9155 Label arg1_is_object, check_undefined_arg1; 9674 Label arg1_is_object, check_undefined_arg1;
9156 Label arg2_is_object, check_undefined_arg2; 9675 Label arg2_is_object, check_undefined_arg2;
9157 Label load_arg2, done; 9676 Label load_arg2, done;
9158 9677
9159 if (!number_info.IsHeapNumber()) { 9678 if (!number_info.IsHeapNumber()) {
9160 if (!number_info.IsSmi()) { 9679 if (!number_info.IsSmi()) {
9161 __ test(edx, Immediate(kSmiTagMask)); 9680 __ test(edx, Immediate(kSmiTagMask));
9162 __ j(not_zero, &arg1_is_object); 9681 __ j(not_zero, &arg1_is_object);
9682 } else {
9683 if (FLAG_debug_code) __ AbortIfNotSmi(edx);
9163 } 9684 }
9164 __ SmiUntag(edx); 9685 __ SmiUntag(edx);
9165 __ jmp(&load_arg2); 9686 __ jmp(&load_arg2);
9166 } 9687 }
9167 9688
9168 __ bind(&arg1_is_object); 9689 __ bind(&arg1_is_object);
9169 9690
9170 // Get the untagged integer version of the edx heap number in ecx. 9691 // Get the untagged integer version of the edx heap number in ecx.
9171 IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure); 9692 IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure);
9172 __ mov(edx, ecx); 9693 __ mov(edx, ecx);
9173 9694
9174 // Here edx has the untagged integer, eax has a Smi or a heap number. 9695 // Here edx has the untagged integer, eax has a Smi or a heap number.
9175 __ bind(&load_arg2); 9696 __ bind(&load_arg2);
9176 if (!number_info.IsHeapNumber()) { 9697 if (!number_info.IsHeapNumber()) {
9177 // Test if arg2 is a Smi. 9698 // Test if arg2 is a Smi.
9178 if (!number_info.IsSmi()) { 9699 if (!number_info.IsSmi()) {
9179 __ test(eax, Immediate(kSmiTagMask)); 9700 __ test(eax, Immediate(kSmiTagMask));
9180 __ j(not_zero, &arg2_is_object); 9701 __ j(not_zero, &arg2_is_object);
9702 } else {
9703 if (FLAG_debug_code) __ AbortIfNotSmi(eax);
9181 } 9704 }
9182 __ SmiUntag(eax); 9705 __ SmiUntag(eax);
9183 __ mov(ecx, eax); 9706 __ mov(ecx, eax);
9184 __ jmp(&done); 9707 __ jmp(&done);
9185 } 9708 }
9186 9709
9187 __ bind(&arg2_is_object); 9710 __ bind(&arg2_is_object);
9188 9711
9189 // Get the untagged integer version of the eax heap number in ecx. 9712 // Get the untagged integer version of the eax heap number in ecx.
9190 IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure); 9713 IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure);
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after
10058 // edx: number of capture registers 10581 // edx: number of capture registers
10059 Label next_capture, done; 10582 Label next_capture, done;
10060 __ mov(eax, Operand(esp, kPreviousIndexOffset)); 10583 __ mov(eax, Operand(esp, kPreviousIndexOffset));
10061 // Capture register counter starts from number of capture registers and 10584 // Capture register counter starts from number of capture registers and
10062 // counts down until wraping after zero. 10585 // counts down until wraping after zero.
10063 __ bind(&next_capture); 10586 __ bind(&next_capture);
10064 __ sub(Operand(edx), Immediate(1)); 10587 __ sub(Operand(edx), Immediate(1));
10065 __ j(negative, &done); 10588 __ j(negative, &done);
10066 // Read the value from the static offsets vector buffer. 10589 // Read the value from the static offsets vector buffer.
10067 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); 10590 __ mov(edi, Operand(ecx, edx, times_int_size, 0));
10068 // Perform explicit shift 10591 __ SmiTag(edi);
10069 ASSERT_EQ(0, kSmiTag);
10070 __ shl(edi, kSmiTagSize);
10071 // Add previous index (from its stack slot) if value is not negative.
10072 Label capture_negative;
10073 // Carry flag set by shift above.
10074 __ j(negative, &capture_negative, not_taken);
10075 __ add(edi, Operand(eax)); // Add previous index (adding smi to smi).
10076 __ bind(&capture_negative);
10077 // Store the smi value in the last match info. 10592 // Store the smi value in the last match info.
10078 __ mov(FieldOperand(ebx, 10593 __ mov(FieldOperand(ebx,
10079 edx, 10594 edx,
10080 times_pointer_size, 10595 times_pointer_size,
10081 RegExpImpl::kFirstCaptureOffset), 10596 RegExpImpl::kFirstCaptureOffset),
10082 edi); 10597 edi);
10083 __ jmp(&next_capture); 10598 __ jmp(&next_capture);
10084 __ bind(&done); 10599 __ bind(&done);
10085 10600
10086 // Return last match info. 10601 // Return last match info.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
10155 // Generate code to lookup number in the number string cache. 10670 // Generate code to lookup number in the number string cache.
10156 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime); 10671 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime);
10157 __ ret(1 * kPointerSize); 10672 __ ret(1 * kPointerSize);
10158 10673
10159 __ bind(&runtime); 10674 __ bind(&runtime);
10160 // Handle number to string in the runtime system if not found in the cache. 10675 // Handle number to string in the runtime system if not found in the cache.
10161 __ TailCallRuntime(Runtime::kNumberToString, 1, 1); 10676 __ TailCallRuntime(Runtime::kNumberToString, 1, 1);
10162 } 10677 }
10163 10678
10164 10679
10680 void RecordWriteStub::Generate(MacroAssembler* masm) {
10681 masm->RecordWriteHelper(object_, addr_, scratch_);
10682 masm->ret(0);
10683 }
10684
10685
10165 void CompareStub::Generate(MacroAssembler* masm) { 10686 void CompareStub::Generate(MacroAssembler* masm) {
10166 Label call_builtin, done; 10687 Label call_builtin, done;
10167 10688
10168 // NOTICE! This code is only reached after a smi-fast-case check, so 10689 // NOTICE! This code is only reached after a smi-fast-case check, so
10169 // it is certain that at least one operand isn't a smi. 10690 // it is certain that at least one operand isn't a smi.
10170 10691
10171 if (cc_ == equal) { // Both strict and non-strict. 10692 if (cc_ == equal) { // Both strict and non-strict.
10172 Label slow; // Fallthrough label. 10693 Label slow; // Fallthrough label.
10173 // Equality is almost reflexive (everything but NaN), so start by testing 10694 // Equality is almost reflexive (everything but NaN), so start by testing
10174 // for "identity and not NaN". 10695 // for "identity and not NaN".
(...skipping 1578 matching lines...) Expand 10 before | Expand all | Expand 10 after
11753 12274
11754 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12275 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
11755 // tagged as a small integer. 12276 // tagged as a small integer.
11756 __ bind(&runtime); 12277 __ bind(&runtime);
11757 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12278 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
11758 } 12279 }
11759 12280
11760 #undef __ 12281 #undef __
11761 12282
11762 } } // namespace v8::internal 12283 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698