OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_size_one_array); | 3450 __ j(not_equal, ¬_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(¬_size_one_array); | 3455 __ bind(¬_size_one_array); |
(...skipping 13 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |