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

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

Issue 8086021: Clean up the x86 assembler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 __ int3(); 131 __ int3();
132 } 132 }
133 #endif 133 #endif
134 134
135 // Strict mode functions and builtins need to replace the receiver 135 // Strict mode functions and builtins need to replace the receiver
136 // with undefined when called as functions (without an explicit 136 // with undefined when called as functions (without an explicit
137 // receiver object). ecx is zero for method calls and non-zero for 137 // receiver object). ecx is zero for method calls and non-zero for
138 // function calls. 138 // function calls.
139 if (info->is_strict_mode() || info->is_native()) { 139 if (info->is_strict_mode() || info->is_native()) {
140 Label ok; 140 Label ok;
141 __ test(ecx, Operand(ecx)); 141 __ test(ecx, ecx);
142 __ j(zero, &ok, Label::kNear); 142 __ j(zero, &ok, Label::kNear);
143 // +1 for return address. 143 // +1 for return address.
144 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; 144 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
145 __ mov(Operand(esp, receiver_offset), 145 __ mov(Operand(esp, receiver_offset),
146 Immediate(isolate()->factory()->undefined_value())); 146 Immediate(isolate()->factory()->undefined_value()));
147 __ bind(&ok); 147 __ bind(&ok);
148 } 148 }
149 149
150 // Open a frame scope to indicate that there is a frame on the stack. The 150 // Open a frame scope to indicate that there is a frame on the stack. The
151 // MANUAL indicates that the scope shouldn't actually generate code to set up 151 // MANUAL indicates that the scope shouldn't actually generate code to set up
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // for the debugger's requirements. 364 // for the debugger's requirements.
365 ASSERT(Assembler::kJSReturnSequenceLength <= 365 ASSERT(Assembler::kJSReturnSequenceLength <=
366 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 366 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
367 #endif 367 #endif
368 } 368 }
369 } 369 }
370 370
371 371
372 void FullCodeGenerator::verify_stack_height() { 372 void FullCodeGenerator::verify_stack_height() {
373 ASSERT(FLAG_verify_stack_height); 373 ASSERT(FLAG_verify_stack_height);
374 __ sub(Operand(ebp), Immediate(kPointerSize * stack_height())); 374 __ sub(ebp, Immediate(kPointerSize * stack_height()));
375 __ cmp(ebp, Operand(esp)); 375 __ cmp(ebp, esp);
376 __ Assert(equal, "Full codegen stack height not as expected."); 376 __ Assert(equal, "Full codegen stack height not as expected.");
377 __ add(Operand(ebp), Immediate(kPointerSize * stack_height())); 377 __ add(ebp, Immediate(kPointerSize * stack_height()));
378 } 378 }
379 379
380 380
381 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { 381 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
382 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 382 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
383 } 383 }
384 384
385 385
386 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 386 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
387 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 387 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 } 596 }
597 597
598 598
599 void FullCodeGenerator::DoTest(Expression* condition, 599 void FullCodeGenerator::DoTest(Expression* condition,
600 Label* if_true, 600 Label* if_true,
601 Label* if_false, 601 Label* if_false,
602 Label* fall_through) { 602 Label* fall_through) {
603 ToBooleanStub stub(result_register()); 603 ToBooleanStub stub(result_register());
604 __ push(result_register()); 604 __ push(result_register());
605 __ CallStub(&stub, condition->test_id()); 605 __ CallStub(&stub, condition->test_id());
606 __ test(result_register(), Operand(result_register())); 606 __ test(result_register(), result_register());
607 // The stub returns nonzero for true. 607 // The stub returns nonzero for true.
608 Split(not_zero, if_true, if_false, fall_through); 608 Split(not_zero, if_true, if_false, fall_through);
609 } 609 }
610 610
611 611
612 void FullCodeGenerator::Split(Condition cc, 612 void FullCodeGenerator::Split(Condition cc,
613 Label* if_true, 613 Label* if_true,
614 Label* if_false, 614 Label* if_false,
615 Label* fall_through) { 615 Label* fall_through) {
616 if (if_false == fall_through) { 616 if (if_false == fall_through) {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 // Compile the label expression. 840 // Compile the label expression.
841 VisitForAccumulatorValue(clause->label()); 841 VisitForAccumulatorValue(clause->label());
842 842
843 // Perform the comparison as if via '==='. 843 // Perform the comparison as if via '==='.
844 __ mov(edx, Operand(esp, 0)); // Switch value. 844 __ mov(edx, Operand(esp, 0)); // Switch value.
845 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 845 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
846 JumpPatchSite patch_site(masm_); 846 JumpPatchSite patch_site(masm_);
847 if (inline_smi_code) { 847 if (inline_smi_code) {
848 Label slow_case; 848 Label slow_case;
849 __ mov(ecx, edx); 849 __ mov(ecx, edx);
850 __ or_(ecx, Operand(eax)); 850 __ or_(ecx, eax);
851 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 851 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
852 852
853 __ cmp(edx, Operand(eax)); 853 __ cmp(edx, eax);
854 __ j(not_equal, &next_test); 854 __ j(not_equal, &next_test);
855 __ Drop(1); // Switch value is no longer needed. 855 __ Drop(1); // Switch value is no longer needed.
856 __ jmp(clause->body_target()); 856 __ jmp(clause->body_target());
857 __ bind(&slow_case); 857 __ bind(&slow_case);
858 } 858 }
859 859
860 // Record position before stub call for type feedback. 860 // Record position before stub call for type feedback.
861 SetSourcePosition(clause->position()); 861 SetSourcePosition(clause->position());
862 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 862 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
863 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 863 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
864 patch_site.EmitPatchInfo(); 864 patch_site.EmitPatchInfo();
865 __ test(eax, Operand(eax)); 865 __ test(eax, eax);
866 __ j(not_equal, &next_test); 866 __ j(not_equal, &next_test);
867 __ Drop(1); // Switch value is no longer needed. 867 __ Drop(1); // Switch value is no longer needed.
868 __ jmp(clause->body_target()); 868 __ jmp(clause->body_target());
869 } 869 }
870 870
871 // Discard the test value and jump to the default if present, otherwise to 871 // Discard the test value and jump to the default if present, otherwise to
872 // the end of the statement. 872 // the end of the statement.
873 __ bind(&next_test); 873 __ bind(&next_test);
874 __ Drop(1); // Switch value is no longer needed. 874 __ Drop(1); // Switch value is no longer needed.
875 if (default_clause == NULL) { 875 if (default_clause == NULL) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 __ JumpIfSmi(edx, &call_runtime); 944 __ JumpIfSmi(edx, &call_runtime);
945 945
946 // Check that there is an enum cache in the non-empty instance 946 // Check that there is an enum cache in the non-empty instance
947 // descriptors (edx). This is the case if the next enumeration 947 // descriptors (edx). This is the case if the next enumeration
948 // index field does not contain a smi. 948 // index field does not contain a smi.
949 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 949 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
950 __ JumpIfSmi(edx, &call_runtime); 950 __ JumpIfSmi(edx, &call_runtime);
951 951
952 // For all objects but the receiver, check that the cache is empty. 952 // For all objects but the receiver, check that the cache is empty.
953 Label check_prototype; 953 Label check_prototype;
954 __ cmp(ecx, Operand(eax)); 954 __ cmp(ecx, eax);
955 __ j(equal, &check_prototype, Label::kNear); 955 __ j(equal, &check_prototype, Label::kNear);
956 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 956 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
957 __ cmp(edx, isolate()->factory()->empty_fixed_array()); 957 __ cmp(edx, isolate()->factory()->empty_fixed_array());
958 __ j(not_equal, &call_runtime); 958 __ j(not_equal, &call_runtime);
959 959
960 // Load the prototype from the map and loop if non-null. 960 // Load the prototype from the map and loop if non-null.
961 __ bind(&check_prototype); 961 __ bind(&check_prototype);
962 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 962 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
963 __ cmp(ecx, isolate()->factory()->null_value()); 963 __ cmp(ecx, isolate()->factory()->null_value());
964 __ j(not_equal, &next); 964 __ j(not_equal, &next);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1026 __ mov(ecx, Operand(esp, 4 * kPointerSize));
1027 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 1027 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1028 __ j(equal, &update_each, Label::kNear); 1028 __ j(equal, &update_each, Label::kNear);
1029 1029
1030 // Convert the entry to a string or null if it isn't a property 1030 // Convert the entry to a string or null if it isn't a property
1031 // anymore. If the property has been removed while iterating, we 1031 // anymore. If the property has been removed while iterating, we
1032 // just skip it. 1032 // just skip it.
1033 __ push(ecx); // Enumerable. 1033 __ push(ecx); // Enumerable.
1034 __ push(ebx); // Current entry. 1034 __ push(ebx); // Current entry.
1035 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1035 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1036 __ test(eax, Operand(eax)); 1036 __ test(eax, eax);
1037 __ j(equal, loop_statement.continue_label()); 1037 __ j(equal, loop_statement.continue_label());
1038 __ mov(ebx, Operand(eax)); 1038 __ mov(ebx, eax);
1039 1039
1040 // Update the 'each' property or variable from the possibly filtered 1040 // Update the 'each' property or variable from the possibly filtered
1041 // entry in register ebx. 1041 // entry in register ebx.
1042 __ bind(&update_each); 1042 __ bind(&update_each);
1043 __ mov(result_register(), ebx); 1043 __ mov(result_register(), ebx);
1044 // Perform the assignment as if via '='. 1044 // Perform the assignment as if via '='.
1045 { EffectContext context(this); 1045 { EffectContext context(this);
1046 EmitAssignment(stmt->each(), stmt->AssignmentId()); 1046 EmitAssignment(stmt->each(), stmt->AssignmentId());
1047 } 1047 }
1048 1048
1049 // Generate code for the body of the loop. 1049 // Generate code for the body of the loop.
1050 Visit(stmt->body()); 1050 Visit(stmt->body());
1051 1051
1052 // Generate code for going to the next element by incrementing the 1052 // Generate code for going to the next element by incrementing the
1053 // index (smi) stored on top of the stack. 1053 // index (smi) stored on top of the stack.
1054 __ bind(loop_statement.continue_label()); 1054 __ bind(loop_statement.continue_label());
1055 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 1055 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1056 1056
1057 EmitStackCheck(stmt); 1057 EmitStackCheck(stmt);
1058 __ jmp(&loop); 1058 __ jmp(&loop);
1059 1059
1060 // Remove the pointers stored on the stack. 1060 // Remove the pointers stored on the stack.
1061 __ bind(loop_statement.break_label()); 1061 __ bind(loop_statement.break_label());
1062 __ add(Operand(esp), Immediate(5 * kPointerSize)); 1062 __ add(esp, Immediate(5 * kPointerSize));
1063 1063
1064 decrement_stack_height(ForIn::kElementCount); 1064 decrement_stack_height(ForIn::kElementCount);
1065 // Exit and decrement the loop depth. 1065 // Exit and decrement the loop depth.
1066 __ bind(&exit); 1066 __ bind(&exit);
1067 decrement_loop_depth(); 1067 decrement_loop_depth();
1068 } 1068 }
1069 1069
1070 1070
1071 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 1071 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1072 bool pretenure) { 1072 bool pretenure) {
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 Token::Value op, 1658 Token::Value op,
1659 OverwriteMode mode, 1659 OverwriteMode mode,
1660 Expression* left, 1660 Expression* left,
1661 Expression* right) { 1661 Expression* right) {
1662 // Do combined smi check of the operands. Left operand is on the 1662 // Do combined smi check of the operands. Left operand is on the
1663 // stack. Right operand is in eax. 1663 // stack. Right operand is in eax.
1664 Label smi_case, done, stub_call; 1664 Label smi_case, done, stub_call;
1665 __ pop(edx); 1665 __ pop(edx);
1666 decrement_stack_height(); 1666 decrement_stack_height();
1667 __ mov(ecx, eax); 1667 __ mov(ecx, eax);
1668 __ or_(eax, Operand(edx)); 1668 __ or_(eax, edx);
1669 JumpPatchSite patch_site(masm_); 1669 JumpPatchSite patch_site(masm_);
1670 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 1670 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
1671 1671
1672 __ bind(&stub_call); 1672 __ bind(&stub_call);
1673 __ mov(eax, ecx); 1673 __ mov(eax, ecx);
1674 BinaryOpStub stub(op, mode); 1674 BinaryOpStub stub(op, mode);
1675 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 1675 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1676 patch_site.EmitPatchInfo(); 1676 patch_site.EmitPatchInfo();
1677 __ jmp(&done, Label::kNear); 1677 __ jmp(&done, Label::kNear);
1678 1678
(...skipping 29 matching lines...) Expand all
1708 __ shr_cl(eax); 1708 __ shr_cl(eax);
1709 __ test(eax, Immediate(0xc0000000)); 1709 __ test(eax, Immediate(0xc0000000));
1710 __ j(zero, &result_ok); 1710 __ j(zero, &result_ok);
1711 __ SmiTag(ecx); 1711 __ SmiTag(ecx);
1712 __ jmp(&stub_call); 1712 __ jmp(&stub_call);
1713 __ bind(&result_ok); 1713 __ bind(&result_ok);
1714 __ SmiTag(eax); 1714 __ SmiTag(eax);
1715 break; 1715 break;
1716 } 1716 }
1717 case Token::ADD: 1717 case Token::ADD:
1718 __ add(eax, Operand(ecx)); 1718 __ add(eax, ecx);
1719 __ j(overflow, &stub_call); 1719 __ j(overflow, &stub_call);
1720 break; 1720 break;
1721 case Token::SUB: 1721 case Token::SUB:
1722 __ sub(eax, Operand(ecx)); 1722 __ sub(eax, ecx);
1723 __ j(overflow, &stub_call); 1723 __ j(overflow, &stub_call);
1724 break; 1724 break;
1725 case Token::MUL: { 1725 case Token::MUL: {
1726 __ SmiUntag(eax); 1726 __ SmiUntag(eax);
1727 __ imul(eax, Operand(ecx)); 1727 __ imul(eax, ecx);
1728 __ j(overflow, &stub_call); 1728 __ j(overflow, &stub_call);
1729 __ test(eax, Operand(eax)); 1729 __ test(eax, eax);
1730 __ j(not_zero, &done, Label::kNear); 1730 __ j(not_zero, &done, Label::kNear);
1731 __ mov(ebx, edx); 1731 __ mov(ebx, edx);
1732 __ or_(ebx, Operand(ecx)); 1732 __ or_(ebx, ecx);
1733 __ j(negative, &stub_call); 1733 __ j(negative, &stub_call);
1734 break; 1734 break;
1735 } 1735 }
1736 case Token::BIT_OR: 1736 case Token::BIT_OR:
1737 __ or_(eax, Operand(ecx)); 1737 __ or_(eax, ecx);
1738 break; 1738 break;
1739 case Token::BIT_AND: 1739 case Token::BIT_AND:
1740 __ and_(eax, Operand(ecx)); 1740 __ and_(eax, ecx);
1741 break; 1741 break;
1742 case Token::BIT_XOR: 1742 case Token::BIT_XOR:
1743 __ xor_(eax, Operand(ecx)); 1743 __ xor_(eax, ecx);
1744 break; 1744 break;
1745 default: 1745 default:
1746 UNREACHABLE(); 1746 UNREACHABLE();
1747 } 1747 }
1748 1748
1749 __ bind(&done); 1749 __ bind(&done);
1750 context()->Plug(eax); 1750 context()->Plug(eax);
1751 } 1751 }
1752 1752
1753 1753
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after
2478 __ LoadInstanceDescriptors(ebx, ebx); 2478 __ LoadInstanceDescriptors(ebx, ebx);
2479 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 2479 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
2480 // ebx: descriptor array 2480 // ebx: descriptor array
2481 // ecx: length of descriptor array 2481 // ecx: length of descriptor array
2482 // Calculate the end of the descriptor array. 2482 // Calculate the end of the descriptor array.
2483 STATIC_ASSERT(kSmiTag == 0); 2483 STATIC_ASSERT(kSmiTag == 0);
2484 STATIC_ASSERT(kSmiTagSize == 1); 2484 STATIC_ASSERT(kSmiTagSize == 1);
2485 STATIC_ASSERT(kPointerSize == 4); 2485 STATIC_ASSERT(kPointerSize == 4);
2486 __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); 2486 __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
2487 // Calculate location of the first key name. 2487 // Calculate location of the first key name.
2488 __ add(Operand(ebx), 2488 __ add(ebx,
2489 Immediate(FixedArray::kHeaderSize + 2489 Immediate(FixedArray::kHeaderSize +
2490 DescriptorArray::kFirstIndex * kPointerSize)); 2490 DescriptorArray::kFirstIndex * kPointerSize));
2491 // Loop through all the keys in the descriptor array. If one of these is the 2491 // Loop through all the keys in the descriptor array. If one of these is the
2492 // symbol valueOf the result is false. 2492 // symbol valueOf the result is false.
2493 Label entry, loop; 2493 Label entry, loop;
2494 __ jmp(&entry); 2494 __ jmp(&entry);
2495 __ bind(&loop); 2495 __ bind(&loop);
2496 __ mov(edx, FieldOperand(ebx, 0)); 2496 __ mov(edx, FieldOperand(ebx, 0));
2497 __ cmp(edx, FACTORY->value_of_symbol()); 2497 __ cmp(edx, FACTORY->value_of_symbol());
2498 __ j(equal, if_false); 2498 __ j(equal, if_false);
2499 __ add(Operand(ebx), Immediate(kPointerSize)); 2499 __ add(ebx, Immediate(kPointerSize));
2500 __ bind(&entry); 2500 __ bind(&entry);
2501 __ cmp(ebx, Operand(ecx)); 2501 __ cmp(ebx, ecx);
2502 __ j(not_equal, &loop); 2502 __ j(not_equal, &loop);
2503 2503
2504 // Reload map as register ebx was used as temporary above. 2504 // Reload map as register ebx was used as temporary above.
2505 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2505 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2506 2506
2507 // If a valueOf property is not found on the object check that it's 2507 // If a valueOf property is not found on the object check that it's
2508 // prototype is the un-modified String prototype. If not result is false. 2508 // prototype is the un-modified String prototype. If not result is false.
2509 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 2509 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
2510 __ JumpIfSmi(ecx, if_false); 2510 __ JumpIfSmi(ecx, if_false);
2511 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); 2511 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2631 2631
2632 Label materialize_true, materialize_false; 2632 Label materialize_true, materialize_false;
2633 Label* if_true = NULL; 2633 Label* if_true = NULL;
2634 Label* if_false = NULL; 2634 Label* if_false = NULL;
2635 Label* fall_through = NULL; 2635 Label* fall_through = NULL;
2636 context()->PrepareTest(&materialize_true, &materialize_false, 2636 context()->PrepareTest(&materialize_true, &materialize_false,
2637 &if_true, &if_false, &fall_through); 2637 &if_true, &if_false, &fall_through);
2638 2638
2639 __ pop(ebx); 2639 __ pop(ebx);
2640 decrement_stack_height(); 2640 decrement_stack_height();
2641 __ cmp(eax, Operand(ebx)); 2641 __ cmp(eax, ebx);
2642 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2642 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2643 Split(equal, if_true, if_false, fall_through); 2643 Split(equal, if_true, if_false, fall_through);
2644 2644
2645 context()->Plug(if_true, if_false); 2645 context()->Plug(if_true, if_false);
2646 } 2646 }
2647 2647
2648 2648
2649 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2649 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2650 ASSERT(args->length() == 1); 2650 ASSERT(args->length() == 1);
2651 2651
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2785 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 2785 __ CallCFunction(ExternalReference::random_uint32_function(isolate()),
2786 1); 2786 1);
2787 2787
2788 // Convert 32 random bits in eax to 0.(32 random bits) in a double 2788 // Convert 32 random bits in eax to 0.(32 random bits) in a double
2789 // by computing: 2789 // by computing:
2790 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2790 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2791 // This is implemented on both SSE2 and FPU. 2791 // This is implemented on both SSE2 and FPU.
2792 if (CpuFeatures::IsSupported(SSE2)) { 2792 if (CpuFeatures::IsSupported(SSE2)) {
2793 CpuFeatures::Scope fscope(SSE2); 2793 CpuFeatures::Scope fscope(SSE2);
2794 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2794 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2795 __ movd(xmm1, Operand(ebx)); 2795 __ movd(xmm1, ebx);
2796 __ movd(xmm0, Operand(eax)); 2796 __ movd(xmm0, eax);
2797 __ cvtss2sd(xmm1, xmm1); 2797 __ cvtss2sd(xmm1, xmm1);
2798 __ xorps(xmm0, xmm1); 2798 __ xorps(xmm0, xmm1);
2799 __ subsd(xmm0, xmm1); 2799 __ subsd(xmm0, xmm1);
2800 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); 2800 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2801 } else { 2801 } else {
2802 // 0x4130000000000000 is 1.0 x 2^20 as a double. 2802 // 0x4130000000000000 is 1.0 x 2^20 as a double.
2803 __ mov(FieldOperand(edi, HeapNumber::kExponentOffset), 2803 __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2804 Immediate(0x41300000)); 2804 Immediate(0x41300000));
2805 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax); 2805 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2806 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2806 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
3164 // Check the object's elements are in fast case and writable. 3164 // Check the object's elements are in fast case and writable.
3165 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); 3165 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
3166 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), 3166 __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
3167 Immediate(isolate()->factory()->fixed_array_map())); 3167 Immediate(isolate()->factory()->fixed_array_map()));
3168 __ j(not_equal, &slow_case); 3168 __ j(not_equal, &slow_case);
3169 3169
3170 // Check that both indices are smis. 3170 // Check that both indices are smis.
3171 __ mov(index_1, Operand(esp, 1 * kPointerSize)); 3171 __ mov(index_1, Operand(esp, 1 * kPointerSize));
3172 __ mov(index_2, Operand(esp, 0)); 3172 __ mov(index_2, Operand(esp, 0));
3173 __ mov(temp, index_1); 3173 __ mov(temp, index_1);
3174 __ or_(temp, Operand(index_2)); 3174 __ or_(temp, index_2);
3175 __ JumpIfNotSmi(temp, &slow_case); 3175 __ JumpIfNotSmi(temp, &slow_case);
3176 3176
3177 // Check that both indices are valid. 3177 // Check that both indices are valid.
3178 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset)); 3178 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
3179 __ cmp(temp, Operand(index_1)); 3179 __ cmp(temp, index_1);
3180 __ j(below_equal, &slow_case); 3180 __ j(below_equal, &slow_case);
3181 __ cmp(temp, Operand(index_2)); 3181 __ cmp(temp, index_2);
3182 __ j(below_equal, &slow_case); 3182 __ j(below_equal, &slow_case);
3183 3183
3184 // Bring addresses into index1 and index2. 3184 // Bring addresses into index1 and index2.
3185 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); 3185 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
3186 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); 3186 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
3187 3187
3188 // Swap elements. Use object and temp as scratch registers. 3188 // Swap elements. Use object and temp as scratch registers.
3189 __ mov(object, Operand(index_1, 0)); 3189 __ mov(object, Operand(index_1, 0));
3190 __ mov(temp, Operand(index_2, 0)); 3190 __ mov(temp, Operand(index_2, 0));
3191 __ mov(Operand(index_2, 0), object); 3191 __ mov(Operand(index_2, 0), object);
(...skipping 20 matching lines...) Expand all
3212 MacroAssembler::kFallThroughAtEnd); 3212 MacroAssembler::kFallThroughAtEnd);
3213 __ RememberedSetHelper(elements, 3213 __ RememberedSetHelper(elements,
3214 index_2, 3214 index_2,
3215 temp, 3215 temp,
3216 kDontSaveFPRegs, 3216 kDontSaveFPRegs,
3217 MacroAssembler::kFallThroughAtEnd); 3217 MacroAssembler::kFallThroughAtEnd);
3218 3218
3219 __ bind(&no_remembered_set); 3219 __ bind(&no_remembered_set);
3220 3220
3221 // We are done. Drop elements from the stack, and return undefined. 3221 // We are done. Drop elements from the stack, and return undefined.
3222 __ add(Operand(esp), Immediate(3 * kPointerSize)); 3222 __ add(esp, Immediate(3 * kPointerSize));
3223 __ mov(eax, isolate()->factory()->undefined_value()); 3223 __ mov(eax, isolate()->factory()->undefined_value());
3224 __ jmp(&done); 3224 __ jmp(&done);
3225 3225
3226 __ bind(&slow_case); 3226 __ bind(&slow_case);
3227 __ CallRuntime(Runtime::kSwapElements, 3); 3227 __ CallRuntime(Runtime::kSwapElements, 3);
3228 3228
3229 __ bind(&done); 3229 __ bind(&done);
3230 decrement_stack_height(3); 3230 decrement_stack_height(3);
3231 context()->Plug(eax); 3231 context()->Plug(eax);
3232 } 3232 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3285 3285
3286 Register right = eax; 3286 Register right = eax;
3287 Register left = ebx; 3287 Register left = ebx;
3288 Register tmp = ecx; 3288 Register tmp = ecx;
3289 3289
3290 VisitForStackValue(args->at(0)); 3290 VisitForStackValue(args->at(0));
3291 VisitForAccumulatorValue(args->at(1)); 3291 VisitForAccumulatorValue(args->at(1));
3292 __ pop(left); 3292 __ pop(left);
3293 3293
3294 Label done, fail, ok; 3294 Label done, fail, ok;
3295 __ cmp(left, Operand(right)); 3295 __ cmp(left, right);
3296 __ j(equal, &ok); 3296 __ j(equal, &ok);
3297 // Fail if either is a non-HeapObject. 3297 // Fail if either is a non-HeapObject.
3298 __ mov(tmp, left); 3298 __ mov(tmp, left);
3299 __ and_(Operand(tmp), right); 3299 __ and_(tmp, right);
3300 __ JumpIfSmi(tmp, &fail); 3300 __ JumpIfSmi(tmp, &fail);
3301 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset)); 3301 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
3302 __ CmpInstanceType(tmp, JS_REGEXP_TYPE); 3302 __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
3303 __ j(not_equal, &fail); 3303 __ j(not_equal, &fail);
3304 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); 3304 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3305 __ j(not_equal, &fail); 3305 __ j(not_equal, &fail);
3306 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 3306 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3307 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 3307 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3308 __ j(equal, &ok); 3308 __ j(equal, &ok);
3309 __ bind(&fail); 3309 __ bind(&fail);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3380 3380
3381 Register scratch = ebx; 3381 Register scratch = ebx;
3382 3382
3383 Register array_length = edi; 3383 Register array_length = edi;
3384 Register result_pos = no_reg; // Will be edi. 3384 Register result_pos = no_reg; // Will be edi.
3385 3385
3386 // Separator operand is already pushed. 3386 // Separator operand is already pushed.
3387 Operand separator_operand = Operand(esp, 2 * kPointerSize); 3387 Operand separator_operand = Operand(esp, 2 * kPointerSize);
3388 Operand result_operand = Operand(esp, 1 * kPointerSize); 3388 Operand result_operand = Operand(esp, 1 * kPointerSize);
3389 Operand array_length_operand = Operand(esp, 0); 3389 Operand array_length_operand = Operand(esp, 0);
3390 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 3390 __ sub(esp, Immediate(2 * kPointerSize));
3391 __ cld(); 3391 __ cld();
3392 // Check that the array is a JSArray 3392 // Check that the array is a JSArray
3393 __ JumpIfSmi(array, &bailout); 3393 __ JumpIfSmi(array, &bailout);
3394 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3394 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3395 __ j(not_equal, &bailout); 3395 __ j(not_equal, &bailout);
3396 3396
3397 // Check that the array has fast elements. 3397 // Check that the array has fast elements.
3398 __ CheckFastElements(scratch, &bailout); 3398 __ CheckFastElements(scratch, &bailout);
3399 3399
3400 // If the array has length zero, return the empty string. 3400 // If the array has length zero, return the empty string.
(...skipping 15 matching lines...) Expand all
3416 3416
3417 3417
3418 // Check that all array elements are sequential ASCII strings, and 3418 // Check that all array elements are sequential ASCII strings, and
3419 // accumulate the sum of their lengths, as a smi-encoded value. 3419 // accumulate the sum of their lengths, as a smi-encoded value.
3420 __ Set(index, Immediate(0)); 3420 __ Set(index, Immediate(0));
3421 __ Set(string_length, Immediate(0)); 3421 __ Set(string_length, Immediate(0));
3422 // Loop condition: while (index < length). 3422 // Loop condition: while (index < length).
3423 // Live loop registers: index, array_length, string, 3423 // Live loop registers: index, array_length, string,
3424 // scratch, string_length, elements. 3424 // scratch, string_length, elements.
3425 if (FLAG_debug_code) { 3425 if (FLAG_debug_code) {
3426 __ cmp(index, Operand(array_length)); 3426 __ cmp(index, array_length);
3427 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin"); 3427 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3428 } 3428 }
3429 __ bind(&loop); 3429 __ bind(&loop);
3430 __ mov(string, FieldOperand(elements, 3430 __ mov(string, FieldOperand(elements,
3431 index, 3431 index,
3432 times_pointer_size, 3432 times_pointer_size,
3433 FixedArray::kHeaderSize)); 3433 FixedArray::kHeaderSize));
3434 __ JumpIfSmi(string, &bailout); 3434 __ JumpIfSmi(string, &bailout);
3435 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3435 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3436 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3436 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3437 __ and_(scratch, Immediate( 3437 __ and_(scratch, Immediate(
3438 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3438 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3439 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3439 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3440 __ j(not_equal, &bailout); 3440 __ j(not_equal, &bailout);
3441 __ add(string_length, 3441 __ add(string_length,
3442 FieldOperand(string, SeqAsciiString::kLengthOffset)); 3442 FieldOperand(string, SeqAsciiString::kLengthOffset));
3443 __ j(overflow, &bailout); 3443 __ j(overflow, &bailout);
3444 __ add(Operand(index), Immediate(1)); 3444 __ add(index, Immediate(1));
3445 __ cmp(index, Operand(array_length)); 3445 __ cmp(index, array_length);
3446 __ j(less, &loop); 3446 __ j(less, &loop);
3447 3447
3448 // If array_length is 1, return elements[0], a string. 3448 // If array_length is 1, return elements[0], a string.
3449 __ cmp(array_length, 1); 3449 __ cmp(array_length, 1);
3450 __ j(not_equal, &not_size_one_array); 3450 __ j(not_equal, &not_size_one_array);
3451 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); 3451 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3452 __ mov(result_operand, scratch); 3452 __ mov(result_operand, scratch);
3453 __ jmp(&done); 3453 __ jmp(&done);
3454 3454
3455 __ bind(&not_size_one_array); 3455 __ bind(&not_size_one_array);
(...skipping 13 matching lines...) Expand all
3469 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3469 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3470 __ and_(scratch, Immediate( 3470 __ and_(scratch, Immediate(
3471 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3471 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3472 __ cmp(scratch, ASCII_STRING_TYPE); 3472 __ cmp(scratch, ASCII_STRING_TYPE);
3473 __ j(not_equal, &bailout); 3473 __ j(not_equal, &bailout);
3474 3474
3475 // Add (separator length times array_length) - separator length 3475 // Add (separator length times array_length) - separator length
3476 // to string_length. 3476 // to string_length.
3477 __ mov(scratch, separator_operand); 3477 __ mov(scratch, separator_operand);
3478 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); 3478 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3479 __ sub(string_length, Operand(scratch)); // May be negative, temporarily. 3479 __ sub(string_length, scratch); // May be negative, temporarily.
3480 __ imul(scratch, array_length_operand); 3480 __ imul(scratch, array_length_operand);
3481 __ j(overflow, &bailout); 3481 __ j(overflow, &bailout);
3482 __ add(string_length, Operand(scratch)); 3482 __ add(string_length, scratch);
3483 __ j(overflow, &bailout); 3483 __ j(overflow, &bailout);
3484 3484
3485 __ shr(string_length, 1); 3485 __ shr(string_length, 1);
3486 // Live registers and stack values: 3486 // Live registers and stack values:
3487 // string_length 3487 // string_length
3488 // elements 3488 // elements
3489 __ AllocateAsciiString(result_pos, string_length, scratch, 3489 __ AllocateAsciiString(result_pos, string_length, scratch,
3490 index, string, &bailout); 3490 index, string, &bailout);
3491 __ mov(result_operand, result_pos); 3491 __ mov(result_operand, result_pos);
3492 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); 3492 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
(...skipping 20 matching lines...) Expand all
3513 // Get string = array[index]. 3513 // Get string = array[index].
3514 __ mov(string, FieldOperand(elements, index, 3514 __ mov(string, FieldOperand(elements, index,
3515 times_pointer_size, 3515 times_pointer_size,
3516 FixedArray::kHeaderSize)); 3516 FixedArray::kHeaderSize));
3517 __ mov(string_length, 3517 __ mov(string_length,
3518 FieldOperand(string, String::kLengthOffset)); 3518 FieldOperand(string, String::kLengthOffset));
3519 __ shr(string_length, 1); 3519 __ shr(string_length, 1);
3520 __ lea(string, 3520 __ lea(string,
3521 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3521 FieldOperand(string, SeqAsciiString::kHeaderSize));
3522 __ CopyBytes(string, result_pos, string_length, scratch); 3522 __ CopyBytes(string, result_pos, string_length, scratch);
3523 __ add(Operand(index), Immediate(1)); 3523 __ add(index, Immediate(1));
3524 __ bind(&loop_1_condition); 3524 __ bind(&loop_1_condition);
3525 __ cmp(index, array_length_operand); 3525 __ cmp(index, array_length_operand);
3526 __ j(less, &loop_1); // End while (index < length). 3526 __ j(less, &loop_1); // End while (index < length).
3527 __ jmp(&done); 3527 __ jmp(&done);
3528 3528
3529 3529
3530 3530
3531 // One-character separator case 3531 // One-character separator case
3532 __ bind(&one_char_separator); 3532 __ bind(&one_char_separator);
3533 // Replace separator with its ascii character value. 3533 // Replace separator with its ascii character value.
(...skipping 20 matching lines...) Expand all
3554 // Get string = array[index]. 3554 // Get string = array[index].
3555 __ mov(string, FieldOperand(elements, index, 3555 __ mov(string, FieldOperand(elements, index,
3556 times_pointer_size, 3556 times_pointer_size,
3557 FixedArray::kHeaderSize)); 3557 FixedArray::kHeaderSize));
3558 __ mov(string_length, 3558 __ mov(string_length,
3559 FieldOperand(string, String::kLengthOffset)); 3559 FieldOperand(string, String::kLengthOffset));
3560 __ shr(string_length, 1); 3560 __ shr(string_length, 1);
3561 __ lea(string, 3561 __ lea(string,
3562 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3562 FieldOperand(string, SeqAsciiString::kHeaderSize));
3563 __ CopyBytes(string, result_pos, string_length, scratch); 3563 __ CopyBytes(string, result_pos, string_length, scratch);
3564 __ add(Operand(index), Immediate(1)); 3564 __ add(index, Immediate(1));
3565 3565
3566 __ cmp(index, array_length_operand); 3566 __ cmp(index, array_length_operand);
3567 __ j(less, &loop_2); // End while (index < length). 3567 __ j(less, &loop_2); // End while (index < length).
3568 __ jmp(&done); 3568 __ jmp(&done);
3569 3569
3570 3570
3571 // Long separator case (separator is more than one character). 3571 // Long separator case (separator is more than one character).
3572 __ bind(&long_separator); 3572 __ bind(&long_separator);
3573 3573
3574 __ Set(index, Immediate(0)); 3574 __ Set(index, Immediate(0));
(...skipping 20 matching lines...) Expand all
3595 // Get string = array[index]. 3595 // Get string = array[index].
3596 __ mov(string, FieldOperand(elements, index, 3596 __ mov(string, FieldOperand(elements, index,
3597 times_pointer_size, 3597 times_pointer_size,
3598 FixedArray::kHeaderSize)); 3598 FixedArray::kHeaderSize));
3599 __ mov(string_length, 3599 __ mov(string_length,
3600 FieldOperand(string, String::kLengthOffset)); 3600 FieldOperand(string, String::kLengthOffset));
3601 __ shr(string_length, 1); 3601 __ shr(string_length, 1);
3602 __ lea(string, 3602 __ lea(string,
3603 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3603 FieldOperand(string, SeqAsciiString::kHeaderSize));
3604 __ CopyBytes(string, result_pos, string_length, scratch); 3604 __ CopyBytes(string, result_pos, string_length, scratch);
3605 __ add(Operand(index), Immediate(1)); 3605 __ add(index, Immediate(1));
3606 3606
3607 __ cmp(index, array_length_operand); 3607 __ cmp(index, array_length_operand);
3608 __ j(less, &loop_3); // End while (index < length). 3608 __ j(less, &loop_3); // End while (index < length).
3609 __ jmp(&done); 3609 __ jmp(&done);
3610 3610
3611 3611
3612 __ bind(&bailout); 3612 __ bind(&bailout);
3613 __ mov(result_operand, isolate()->factory()->undefined_value()); 3613 __ mov(result_operand, isolate()->factory()->undefined_value());
3614 __ bind(&done); 3614 __ bind(&done);
3615 __ mov(eax, result_operand); 3615 __ mov(eax, result_operand);
3616 // Drop temp values from the stack, and restore context register. 3616 // Drop temp values from the stack, and restore context register.
3617 __ add(Operand(esp), Immediate(3 * kPointerSize)); 3617 __ add(esp, Immediate(3 * kPointerSize));
3618 3618
3619 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3619 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3620 decrement_stack_height(); 3620 decrement_stack_height();
3621 context()->Plug(eax); 3621 context()->Plug(eax);
3622 } 3622 }
3623 3623
3624 3624
3625 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3625 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3626 Handle<String> name = expr->name(); 3626 Handle<String> name = expr->name();
3627 if (name->length() > 0 && name->Get(0) == '_') { 3627 if (name->length() > 0 && name->Get(0) == '_') {
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
3887 } 3887 }
3888 } 3888 }
3889 } 3889 }
3890 3890
3891 // Inline smi case if we are in a loop. 3891 // Inline smi case if we are in a loop.
3892 Label done, stub_call; 3892 Label done, stub_call;
3893 JumpPatchSite patch_site(masm_); 3893 JumpPatchSite patch_site(masm_);
3894 3894
3895 if (ShouldInlineSmiCase(expr->op())) { 3895 if (ShouldInlineSmiCase(expr->op())) {
3896 if (expr->op() == Token::INC) { 3896 if (expr->op() == Token::INC) {
3897 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3897 __ add(eax, Immediate(Smi::FromInt(1)));
3898 } else { 3898 } else {
3899 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3899 __ sub(eax, Immediate(Smi::FromInt(1)));
3900 } 3900 }
3901 __ j(overflow, &stub_call, Label::kNear); 3901 __ j(overflow, &stub_call, Label::kNear);
3902 // We could eliminate this smi check if we split the code at 3902 // We could eliminate this smi check if we split the code at
3903 // the first smi check before calling ToNumber. 3903 // the first smi check before calling ToNumber.
3904 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear); 3904 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear);
3905 3905
3906 __ bind(&stub_call); 3906 __ bind(&stub_call);
3907 // Call stub. Undo operation first. 3907 // Call stub. Undo operation first.
3908 if (expr->op() == Token::INC) { 3908 if (expr->op() == Token::INC) {
3909 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3909 __ sub(eax, Immediate(Smi::FromInt(1)));
3910 } else { 3910 } else {
3911 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3911 __ add(eax, Immediate(Smi::FromInt(1)));
3912 } 3912 }
3913 } 3913 }
3914 3914
3915 // Record position before stub call. 3915 // Record position before stub call.
3916 SetSourcePosition(expr->position()); 3916 SetSourcePosition(expr->position());
3917 3917
3918 // Call stub for +1/-1. 3918 // Call stub for +1/-1.
3919 __ mov(edx, eax); 3919 __ mov(edx, eax);
3920 __ mov(eax, Immediate(Smi::FromInt(1))); 3920 __ mov(eax, Immediate(Smi::FromInt(1)));
3921 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 3921 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
4127 __ cmp(eax, isolate()->factory()->true_value()); 4127 __ cmp(eax, isolate()->factory()->true_value());
4128 Split(equal, if_true, if_false, fall_through); 4128 Split(equal, if_true, if_false, fall_through);
4129 break; 4129 break;
4130 4130
4131 case Token::INSTANCEOF: { 4131 case Token::INSTANCEOF: {
4132 VisitForStackValue(expr->right()); 4132 VisitForStackValue(expr->right());
4133 InstanceofStub stub(InstanceofStub::kNoFlags); 4133 InstanceofStub stub(InstanceofStub::kNoFlags);
4134 __ CallStub(&stub); 4134 __ CallStub(&stub);
4135 decrement_stack_height(2); 4135 decrement_stack_height(2);
4136 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4136 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4137 __ test(eax, Operand(eax)); 4137 __ test(eax, eax);
4138 // The stub returns 0 for true. 4138 // The stub returns 0 for true.
4139 Split(zero, if_true, if_false, fall_through); 4139 Split(zero, if_true, if_false, fall_through);
4140 break; 4140 break;
4141 } 4141 }
4142 4142
4143 default: { 4143 default: {
4144 VisitForAccumulatorValue(expr->right()); 4144 VisitForAccumulatorValue(expr->right());
4145 Condition cc = no_condition; 4145 Condition cc = no_condition;
4146 switch (op) { 4146 switch (op) {
4147 case Token::EQ_STRICT: 4147 case Token::EQ_STRICT:
(...skipping 25 matching lines...) Expand all
4173 case Token::INSTANCEOF: 4173 case Token::INSTANCEOF:
4174 default: 4174 default:
4175 UNREACHABLE(); 4175 UNREACHABLE();
4176 } 4176 }
4177 decrement_stack_height(); 4177 decrement_stack_height();
4178 4178
4179 bool inline_smi_code = ShouldInlineSmiCase(op); 4179 bool inline_smi_code = ShouldInlineSmiCase(op);
4180 JumpPatchSite patch_site(masm_); 4180 JumpPatchSite patch_site(masm_);
4181 if (inline_smi_code) { 4181 if (inline_smi_code) {
4182 Label slow_case; 4182 Label slow_case;
4183 __ mov(ecx, Operand(edx)); 4183 __ mov(ecx, edx);
4184 __ or_(ecx, Operand(eax)); 4184 __ or_(ecx, eax);
4185 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4185 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4186 __ cmp(edx, Operand(eax)); 4186 __ cmp(edx, eax);
4187 Split(cc, if_true, if_false, NULL); 4187 Split(cc, if_true, if_false, NULL);
4188 __ bind(&slow_case); 4188 __ bind(&slow_case);
4189 } 4189 }
4190 4190
4191 // Record position and call the compare IC. 4191 // Record position and call the compare IC.
4192 SetSourcePosition(expr->position()); 4192 SetSourcePosition(expr->position());
4193 Handle<Code> ic = CompareIC::GetUninitialized(op); 4193 Handle<Code> ic = CompareIC::GetUninitialized(op);
4194 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 4194 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4195 patch_site.EmitPatchInfo(); 4195 patch_site.EmitPatchInfo();
4196 4196
4197 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4197 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4198 __ test(eax, Operand(eax)); 4198 __ test(eax, eax);
4199 Split(cc, if_true, if_false, fall_through); 4199 Split(cc, if_true, if_false, fall_through);
4200 } 4200 }
4201 } 4201 }
4202 4202
4203 // Convert the result of the comparison into one expected for this 4203 // Convert the result of the comparison into one expected for this
4204 // expression's context. 4204 // expression's context.
4205 context()->Plug(if_true, if_false); 4205 context()->Plug(if_true, if_false);
4206 } 4206 }
4207 4207
4208 4208
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4289 } 4289 }
4290 4290
4291 4291
4292 // ---------------------------------------------------------------------------- 4292 // ----------------------------------------------------------------------------
4293 // Non-local control flow support. 4293 // Non-local control flow support.
4294 4294
4295 void FullCodeGenerator::EnterFinallyBlock() { 4295 void FullCodeGenerator::EnterFinallyBlock() {
4296 // Cook return address on top of stack (smi encoded Code* delta) 4296 // Cook return address on top of stack (smi encoded Code* delta)
4297 ASSERT(!result_register().is(edx)); 4297 ASSERT(!result_register().is(edx));
4298 __ pop(edx); 4298 __ pop(edx);
4299 __ sub(Operand(edx), Immediate(masm_->CodeObject())); 4299 __ sub(edx, Immediate(masm_->CodeObject()));
4300 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4300 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4301 STATIC_ASSERT(kSmiTag == 0); 4301 STATIC_ASSERT(kSmiTag == 0);
4302 __ SmiTag(edx); 4302 __ SmiTag(edx);
4303 __ push(edx); 4303 __ push(edx);
4304 // Store result register while executing finally block. 4304 // Store result register while executing finally block.
4305 __ push(result_register()); 4305 __ push(result_register());
4306 } 4306 }
4307 4307
4308 4308
4309 void FullCodeGenerator::ExitFinallyBlock() { 4309 void FullCodeGenerator::ExitFinallyBlock() {
4310 ASSERT(!result_register().is(edx)); 4310 ASSERT(!result_register().is(edx));
4311 __ pop(result_register()); 4311 __ pop(result_register());
4312 // Uncook return address. 4312 // Uncook return address.
4313 __ pop(edx); 4313 __ pop(edx);
4314 __ SmiUntag(edx); 4314 __ SmiUntag(edx);
4315 __ add(Operand(edx), Immediate(masm_->CodeObject())); 4315 __ add(edx, Immediate(masm_->CodeObject()));
4316 __ jmp(Operand(edx)); 4316 __ jmp(edx);
4317 } 4317 }
4318 4318
4319 4319
4320 #undef __ 4320 #undef __
4321 4321
4322 #define __ ACCESS_MASM(masm()) 4322 #define __ ACCESS_MASM(masm())
4323 4323
4324 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4324 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4325 int* stack_depth, 4325 int* stack_depth,
4326 int* context_length) { 4326 int* context_length) {
(...skipping 16 matching lines...) Expand all
4343 *context_length = 0; 4343 *context_length = 0;
4344 return previous_; 4344 return previous_;
4345 } 4345 }
4346 4346
4347 4347
4348 #undef __ 4348 #undef __
4349 4349
4350 } } // namespace v8::internal 4350 } } // namespace v8::internal
4351 4351
4352 #endif // V8_TARGET_ARCH_IA32 4352 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698