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

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

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
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
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
151 // MANUAL indicates that the scope shouldn't actually generate code to set up
152 // the frame (that is done below).
153 FrameScope frame_scope(masm_, StackFrame::MANUAL);
154
150 __ push(ebp); // Caller's frame pointer. 155 __ push(ebp); // Caller's frame pointer.
151 __ mov(ebp, esp); 156 __ mov(ebp, esp);
152 __ push(esi); // Callee's context. 157 __ push(esi); // Callee's context.
153 __ push(edi); // Callee's JS Function. 158 __ push(edi); // Callee's JS Function.
154 159
155 { Comment cmnt(masm_, "[ Allocate locals"); 160 { Comment cmnt(masm_, "[ Allocate locals");
156 int locals_count = info->scope()->num_stack_slots(); 161 int locals_count = info->scope()->num_stack_slots();
157 if (locals_count == 1) { 162 if (locals_count == 1) {
158 __ push(Immediate(isolate()->factory()->undefined_value())); 163 __ push(Immediate(isolate()->factory()->undefined_value()));
159 } else if (locals_count > 1) { 164 } else if (locals_count > 1) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 for (int i = 0; i < num_parameters; i++) { 198 for (int i = 0; i < num_parameters; i++) {
194 Variable* var = scope()->parameter(i); 199 Variable* var = scope()->parameter(i);
195 if (var->IsContextSlot()) { 200 if (var->IsContextSlot()) {
196 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 201 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
197 (num_parameters - 1 - i) * kPointerSize; 202 (num_parameters - 1 - i) * kPointerSize;
198 // Load parameter from stack. 203 // Load parameter from stack.
199 __ mov(eax, Operand(ebp, parameter_offset)); 204 __ mov(eax, Operand(ebp, parameter_offset));
200 // Store it in the context. 205 // Store it in the context.
201 int context_offset = Context::SlotOffset(var->index()); 206 int context_offset = Context::SlotOffset(var->index());
202 __ mov(Operand(esi, context_offset), eax); 207 __ mov(Operand(esi, context_offset), eax);
203 // Update the write barrier. This clobbers all involved 208 // Update the write barrier. This clobbers eax and ebx.
204 // registers, so we have use a third register to avoid 209 __ RecordWriteContextSlot(esi,
205 // clobbering esi. 210 context_offset,
206 __ mov(ecx, esi); 211 eax,
207 __ RecordWrite(ecx, context_offset, eax, ebx); 212 ebx,
213 kDontSaveFPRegs);
208 } 214 }
209 } 215 }
210 } 216 }
211 217
212 Variable* arguments = scope()->arguments(); 218 Variable* arguments = scope()->arguments();
213 if (arguments != NULL) { 219 if (arguments != NULL) {
214 // Function uses arguments object. 220 // Function uses arguments object.
215 Comment cmnt(masm_, "[ Allocate arguments object"); 221 Comment cmnt(masm_, "[ Allocate arguments object");
216 if (function_in_register) { 222 if (function_in_register) {
217 __ push(edi); 223 __ push(edi);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 // for the debugger's requirements. 364 // for the debugger's requirements.
359 ASSERT(Assembler::kJSReturnSequenceLength <= 365 ASSERT(Assembler::kJSReturnSequenceLength <=
360 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 366 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
361 #endif 367 #endif
362 } 368 }
363 } 369 }
364 370
365 371
366 void FullCodeGenerator::verify_stack_height() { 372 void FullCodeGenerator::verify_stack_height() {
367 ASSERT(FLAG_verify_stack_height); 373 ASSERT(FLAG_verify_stack_height);
368 __ sub(Operand(ebp), Immediate(kPointerSize * stack_height())); 374 __ sub(ebp, Immediate(kPointerSize * stack_height()));
369 __ cmp(ebp, Operand(esp)); 375 __ cmp(ebp, esp);
370 __ Assert(equal, "Full codegen stack height not as expected."); 376 __ Assert(equal, "Full codegen stack height not as expected.");
371 __ add(Operand(ebp), Immediate(kPointerSize * stack_height())); 377 __ add(ebp, Immediate(kPointerSize * stack_height()));
372 } 378 }
373 379
374 380
375 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { 381 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
376 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 382 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
377 } 383 }
378 384
379 385
380 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 386 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
381 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 387 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 } 596 }
591 597
592 598
593 void FullCodeGenerator::DoTest(Expression* condition, 599 void FullCodeGenerator::DoTest(Expression* condition,
594 Label* if_true, 600 Label* if_true,
595 Label* if_false, 601 Label* if_false,
596 Label* fall_through) { 602 Label* fall_through) {
597 ToBooleanStub stub(result_register()); 603 ToBooleanStub stub(result_register());
598 __ push(result_register()); 604 __ push(result_register());
599 __ CallStub(&stub, condition->test_id()); 605 __ CallStub(&stub, condition->test_id());
600 __ test(result_register(), Operand(result_register())); 606 __ test(result_register(), result_register());
601 // The stub returns nonzero for true. 607 // The stub returns nonzero for true.
602 Split(not_zero, if_true, if_false, fall_through); 608 Split(not_zero, if_true, if_false, fall_through);
603 } 609 }
604 610
605 611
606 void FullCodeGenerator::Split(Condition cc, 612 void FullCodeGenerator::Split(Condition cc,
607 Label* if_true, 613 Label* if_true,
608 Label* if_false, 614 Label* if_false,
609 Label* fall_through) { 615 Label* fall_through) {
610 if (if_false == fall_through) { 616 if (if_false == fall_through) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 void FullCodeGenerator::SetVar(Variable* var, 660 void FullCodeGenerator::SetVar(Variable* var,
655 Register src, 661 Register src,
656 Register scratch0, 662 Register scratch0,
657 Register scratch1) { 663 Register scratch1) {
658 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 664 ASSERT(var->IsContextSlot() || var->IsStackAllocated());
659 ASSERT(!scratch0.is(src)); 665 ASSERT(!scratch0.is(src));
660 ASSERT(!scratch0.is(scratch1)); 666 ASSERT(!scratch0.is(scratch1));
661 ASSERT(!scratch1.is(src)); 667 ASSERT(!scratch1.is(src));
662 MemOperand location = VarOperand(var, scratch0); 668 MemOperand location = VarOperand(var, scratch0);
663 __ mov(location, src); 669 __ mov(location, src);
670
664 // Emit the write barrier code if the location is in the heap. 671 // Emit the write barrier code if the location is in the heap.
665 if (var->IsContextSlot()) { 672 if (var->IsContextSlot()) {
666 int offset = Context::SlotOffset(var->index()); 673 int offset = Context::SlotOffset(var->index());
667 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); 674 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
668 __ RecordWrite(scratch0, offset, src, scratch1); 675 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
669 } 676 }
670 } 677 }
671 678
672 679
673 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 680 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
674 bool should_normalize, 681 bool should_normalize,
675 Label* if_true, 682 Label* if_true,
676 Label* if_false) { 683 Label* if_false) {
677 // Only prepare for bailouts before splits if we're in a test 684 // Only prepare for bailouts before splits if we're in a test
678 // context. Otherwise, we let the Visit function deal with the 685 // context. Otherwise, we let the Visit function deal with the
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); 738 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
732 __ cmp(ebx, isolate()->factory()->with_context_map()); 739 __ cmp(ebx, isolate()->factory()->with_context_map());
733 __ Check(not_equal, "Declaration in with context."); 740 __ Check(not_equal, "Declaration in with context.");
734 __ cmp(ebx, isolate()->factory()->catch_context_map()); 741 __ cmp(ebx, isolate()->factory()->catch_context_map());
735 __ Check(not_equal, "Declaration in catch context."); 742 __ Check(not_equal, "Declaration in catch context.");
736 } 743 }
737 if (function != NULL) { 744 if (function != NULL) {
738 Comment cmnt(masm_, "[ Declaration"); 745 Comment cmnt(masm_, "[ Declaration");
739 VisitForAccumulatorValue(function); 746 VisitForAccumulatorValue(function);
740 __ mov(ContextOperand(esi, variable->index()), result_register()); 747 __ mov(ContextOperand(esi, variable->index()), result_register());
741 int offset = Context::SlotOffset(variable->index()); 748 // We know that we have written a function, which is not a smi.
742 __ mov(ebx, esi); 749 __ RecordWriteContextSlot(esi,
743 __ RecordWrite(ebx, offset, result_register(), ecx); 750 Context::SlotOffset(variable->index()),
751 result_register(),
752 ecx,
753 kDontSaveFPRegs,
754 EMIT_REMEMBERED_SET,
755 OMIT_SMI_CHECK);
744 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 756 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
745 } else if (mode == Variable::CONST || mode == Variable::LET) { 757 } else if (mode == Variable::CONST || mode == Variable::LET) {
746 Comment cmnt(masm_, "[ Declaration"); 758 Comment cmnt(masm_, "[ Declaration");
747 __ mov(ContextOperand(esi, variable->index()), 759 __ mov(ContextOperand(esi, variable->index()),
748 Immediate(isolate()->factory()->the_hole_value())); 760 Immediate(isolate()->factory()->the_hole_value()));
749 // No write barrier since the hole value is in old space. 761 // No write barrier since the hole value is in old space.
750 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 762 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
751 } 763 }
752 break; 764 break;
753 765
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 // Compile the label expression. 840 // Compile the label expression.
829 VisitForAccumulatorValue(clause->label()); 841 VisitForAccumulatorValue(clause->label());
830 842
831 // Perform the comparison as if via '==='. 843 // Perform the comparison as if via '==='.
832 __ mov(edx, Operand(esp, 0)); // Switch value. 844 __ mov(edx, Operand(esp, 0)); // Switch value.
833 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 845 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
834 JumpPatchSite patch_site(masm_); 846 JumpPatchSite patch_site(masm_);
835 if (inline_smi_code) { 847 if (inline_smi_code) {
836 Label slow_case; 848 Label slow_case;
837 __ mov(ecx, edx); 849 __ mov(ecx, edx);
838 __ or_(ecx, Operand(eax)); 850 __ or_(ecx, eax);
839 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 851 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
840 852
841 __ cmp(edx, Operand(eax)); 853 __ cmp(edx, eax);
842 __ j(not_equal, &next_test); 854 __ j(not_equal, &next_test);
843 __ Drop(1); // Switch value is no longer needed. 855 __ Drop(1); // Switch value is no longer needed.
844 __ jmp(clause->body_target()); 856 __ jmp(clause->body_target());
845 __ bind(&slow_case); 857 __ bind(&slow_case);
846 } 858 }
847 859
848 // Record position before stub call for type feedback. 860 // Record position before stub call for type feedback.
849 SetSourcePosition(clause->position()); 861 SetSourcePosition(clause->position());
850 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 862 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
851 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 863 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
852 patch_site.EmitPatchInfo(); 864 patch_site.EmitPatchInfo();
853 __ test(eax, Operand(eax)); 865 __ test(eax, eax);
854 __ j(not_equal, &next_test); 866 __ j(not_equal, &next_test);
855 __ Drop(1); // Switch value is no longer needed. 867 __ Drop(1); // Switch value is no longer needed.
856 __ jmp(clause->body_target()); 868 __ jmp(clause->body_target());
857 } 869 }
858 870
859 // 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
860 // the end of the statement. 872 // the end of the statement.
861 __ bind(&next_test); 873 __ bind(&next_test);
862 __ Drop(1); // Switch value is no longer needed. 874 __ Drop(1); // Switch value is no longer needed.
863 if (default_clause == NULL) { 875 if (default_clause == NULL) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 __ JumpIfSmi(edx, &call_runtime); 944 __ JumpIfSmi(edx, &call_runtime);
933 945
934 // 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
935 // descriptors (edx). This is the case if the next enumeration 947 // descriptors (edx). This is the case if the next enumeration
936 // index field does not contain a smi. 948 // index field does not contain a smi.
937 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 949 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
938 __ JumpIfSmi(edx, &call_runtime); 950 __ JumpIfSmi(edx, &call_runtime);
939 951
940 // 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.
941 Label check_prototype; 953 Label check_prototype;
942 __ cmp(ecx, Operand(eax)); 954 __ cmp(ecx, eax);
943 __ j(equal, &check_prototype, Label::kNear); 955 __ j(equal, &check_prototype, Label::kNear);
944 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 956 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
945 __ cmp(edx, isolate()->factory()->empty_fixed_array()); 957 __ cmp(edx, isolate()->factory()->empty_fixed_array());
946 __ j(not_equal, &call_runtime); 958 __ j(not_equal, &call_runtime);
947 959
948 // Load the prototype from the map and loop if non-null. 960 // Load the prototype from the map and loop if non-null.
949 __ bind(&check_prototype); 961 __ bind(&check_prototype);
950 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 962 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
951 __ cmp(ecx, isolate()->factory()->null_value()); 963 __ cmp(ecx, isolate()->factory()->null_value());
952 __ j(not_equal, &next); 964 __ j(not_equal, &next);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1026 __ mov(ecx, Operand(esp, 4 * kPointerSize));
1015 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 1027 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1016 __ j(equal, &update_each, Label::kNear); 1028 __ j(equal, &update_each, Label::kNear);
1017 1029
1018 // 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
1019 // anymore. If the property has been removed while iterating, we 1031 // anymore. If the property has been removed while iterating, we
1020 // just skip it. 1032 // just skip it.
1021 __ push(ecx); // Enumerable. 1033 __ push(ecx); // Enumerable.
1022 __ push(ebx); // Current entry. 1034 __ push(ebx); // Current entry.
1023 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1035 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1024 __ test(eax, Operand(eax)); 1036 __ test(eax, eax);
1025 __ j(equal, loop_statement.continue_label()); 1037 __ j(equal, loop_statement.continue_label());
1026 __ mov(ebx, Operand(eax)); 1038 __ mov(ebx, eax);
1027 1039
1028 // Update the 'each' property or variable from the possibly filtered 1040 // Update the 'each' property or variable from the possibly filtered
1029 // entry in register ebx. 1041 // entry in register ebx.
1030 __ bind(&update_each); 1042 __ bind(&update_each);
1031 __ mov(result_register(), ebx); 1043 __ mov(result_register(), ebx);
1032 // Perform the assignment as if via '='. 1044 // Perform the assignment as if via '='.
1033 { EffectContext context(this); 1045 { EffectContext context(this);
1034 EmitAssignment(stmt->each(), stmt->AssignmentId()); 1046 EmitAssignment(stmt->each(), stmt->AssignmentId());
1035 } 1047 }
1036 1048
1037 // Generate code for the body of the loop. 1049 // Generate code for the body of the loop.
1038 Visit(stmt->body()); 1050 Visit(stmt->body());
1039 1051
1040 // Generate code for going to the next element by incrementing the 1052 // Generate code for going to the next element by incrementing the
1041 // index (smi) stored on top of the stack. 1053 // index (smi) stored on top of the stack.
1042 __ bind(loop_statement.continue_label()); 1054 __ bind(loop_statement.continue_label());
1043 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 1055 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1044 1056
1045 EmitStackCheck(stmt); 1057 EmitStackCheck(stmt);
1046 __ jmp(&loop); 1058 __ jmp(&loop);
1047 1059
1048 // Remove the pointers stored on the stack. 1060 // Remove the pointers stored on the stack.
1049 __ bind(loop_statement.break_label()); 1061 __ bind(loop_statement.break_label());
1050 __ add(Operand(esp), Immediate(5 * kPointerSize)); 1062 __ add(esp, Immediate(5 * kPointerSize));
1051 1063
1052 decrement_stack_height(ForIn::kElementCount); 1064 decrement_stack_height(ForIn::kElementCount);
1053 // Exit and decrement the loop depth. 1065 // Exit and decrement the loop depth.
1054 __ bind(&exit); 1066 __ bind(&exit);
1055 decrement_loop_depth(); 1067 decrement_loop_depth();
1056 } 1068 }
1057 1069
1058 1070
1059 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 1071 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1060 bool pretenure) { 1072 bool pretenure) {
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 increment_stack_height(); 1485 increment_stack_height();
1474 } 1486 }
1475 VisitForAccumulatorValue(subexpr); 1487 VisitForAccumulatorValue(subexpr);
1476 1488
1477 // Store the subexpression value in the array's elements. 1489 // Store the subexpression value in the array's elements.
1478 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 1490 __ mov(ebx, Operand(esp, 0)); // Copy of array literal.
1479 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 1491 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
1480 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1492 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1481 __ mov(FieldOperand(ebx, offset), result_register()); 1493 __ mov(FieldOperand(ebx, offset), result_register());
1482 1494
1495 Label no_map_change;
1496 __ JumpIfSmi(result_register(), &no_map_change);
1483 // Update the write barrier for the array store. 1497 // Update the write barrier for the array store.
1484 __ RecordWrite(ebx, offset, result_register(), ecx); 1498 __ RecordWriteField(ebx, offset, result_register(), ecx,
1499 kDontSaveFPRegs,
1500 EMIT_REMEMBERED_SET,
1501 OMIT_SMI_CHECK);
1502 if (FLAG_smi_only_arrays) {
1503 __ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
1504 __ CheckFastSmiOnlyElements(edi, &no_map_change, Label::kNear);
1505 __ push(Operand(esp, 0));
1506 __ CallRuntime(Runtime::kNonSmiElementStored, 1);
1507 }
1508 __ bind(&no_map_change);
1485 1509
1486 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1510 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1487 } 1511 }
1488 1512
1489 if (result_saved) { 1513 if (result_saved) {
1490 context()->PlugTOS(); 1514 context()->PlugTOS();
1491 } else { 1515 } else {
1492 context()->Plug(eax); 1516 context()->Plug(eax);
1493 } 1517 }
1494 } 1518 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 Token::Value op, 1658 Token::Value op,
1635 OverwriteMode mode, 1659 OverwriteMode mode,
1636 Expression* left, 1660 Expression* left,
1637 Expression* right) { 1661 Expression* right) {
1638 // 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
1639 // stack. Right operand is in eax. 1663 // stack. Right operand is in eax.
1640 Label smi_case, done, stub_call; 1664 Label smi_case, done, stub_call;
1641 __ pop(edx); 1665 __ pop(edx);
1642 decrement_stack_height(); 1666 decrement_stack_height();
1643 __ mov(ecx, eax); 1667 __ mov(ecx, eax);
1644 __ or_(eax, Operand(edx)); 1668 __ or_(eax, edx);
1645 JumpPatchSite patch_site(masm_); 1669 JumpPatchSite patch_site(masm_);
1646 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 1670 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
1647 1671
1648 __ bind(&stub_call); 1672 __ bind(&stub_call);
1649 __ mov(eax, ecx); 1673 __ mov(eax, ecx);
1650 BinaryOpStub stub(op, mode); 1674 BinaryOpStub stub(op, mode);
1651 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 1675 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1652 patch_site.EmitPatchInfo(); 1676 patch_site.EmitPatchInfo();
1653 __ jmp(&done, Label::kNear); 1677 __ jmp(&done, Label::kNear);
1654 1678
(...skipping 29 matching lines...) Expand all
1684 __ shr_cl(eax); 1708 __ shr_cl(eax);
1685 __ test(eax, Immediate(0xc0000000)); 1709 __ test(eax, Immediate(0xc0000000));
1686 __ j(zero, &result_ok); 1710 __ j(zero, &result_ok);
1687 __ SmiTag(ecx); 1711 __ SmiTag(ecx);
1688 __ jmp(&stub_call); 1712 __ jmp(&stub_call);
1689 __ bind(&result_ok); 1713 __ bind(&result_ok);
1690 __ SmiTag(eax); 1714 __ SmiTag(eax);
1691 break; 1715 break;
1692 } 1716 }
1693 case Token::ADD: 1717 case Token::ADD:
1694 __ add(eax, Operand(ecx)); 1718 __ add(eax, ecx);
1695 __ j(overflow, &stub_call); 1719 __ j(overflow, &stub_call);
1696 break; 1720 break;
1697 case Token::SUB: 1721 case Token::SUB:
1698 __ sub(eax, Operand(ecx)); 1722 __ sub(eax, ecx);
1699 __ j(overflow, &stub_call); 1723 __ j(overflow, &stub_call);
1700 break; 1724 break;
1701 case Token::MUL: { 1725 case Token::MUL: {
1702 __ SmiUntag(eax); 1726 __ SmiUntag(eax);
1703 __ imul(eax, Operand(ecx)); 1727 __ imul(eax, ecx);
1704 __ j(overflow, &stub_call); 1728 __ j(overflow, &stub_call);
1705 __ test(eax, Operand(eax)); 1729 __ test(eax, eax);
1706 __ j(not_zero, &done, Label::kNear); 1730 __ j(not_zero, &done, Label::kNear);
1707 __ mov(ebx, edx); 1731 __ mov(ebx, edx);
1708 __ or_(ebx, Operand(ecx)); 1732 __ or_(ebx, ecx);
1709 __ j(negative, &stub_call); 1733 __ j(negative, &stub_call);
1710 break; 1734 break;
1711 } 1735 }
1712 case Token::BIT_OR: 1736 case Token::BIT_OR:
1713 __ or_(eax, Operand(ecx)); 1737 __ or_(eax, ecx);
1714 break; 1738 break;
1715 case Token::BIT_AND: 1739 case Token::BIT_AND:
1716 __ and_(eax, Operand(ecx)); 1740 __ and_(eax, ecx);
1717 break; 1741 break;
1718 case Token::BIT_XOR: 1742 case Token::BIT_XOR:
1719 __ xor_(eax, Operand(ecx)); 1743 __ xor_(eax, ecx);
1720 break; 1744 break;
1721 default: 1745 default:
1722 UNREACHABLE(); 1746 UNREACHABLE();
1723 } 1747 }
1724 1748
1725 __ bind(&done); 1749 __ bind(&done);
1726 context()->Plug(eax); 1750 context()->Plug(eax);
1727 } 1751 }
1728 1752
1729 1753
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 MemOperand location = VarOperand(var, ecx); 1876 MemOperand location = VarOperand(var, ecx);
1853 __ mov(edx, location); 1877 __ mov(edx, location);
1854 __ cmp(edx, isolate()->factory()->the_hole_value()); 1878 __ cmp(edx, isolate()->factory()->the_hole_value());
1855 __ j(not_equal, &assign, Label::kNear); 1879 __ j(not_equal, &assign, Label::kNear);
1856 __ push(Immediate(var->name())); 1880 __ push(Immediate(var->name()));
1857 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1881 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1858 __ bind(&assign); 1882 __ bind(&assign);
1859 __ mov(location, eax); 1883 __ mov(location, eax);
1860 if (var->IsContextSlot()) { 1884 if (var->IsContextSlot()) {
1861 __ mov(edx, eax); 1885 __ mov(edx, eax);
1862 __ RecordWrite(ecx, Context::SlotOffset(var->index()), edx, ebx); 1886 int offset = Context::SlotOffset(var->index());
1887 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
1863 } 1888 }
1864 } 1889 }
1865 1890
1866 } else if (var->mode() != Variable::CONST) { 1891 } else if (var->mode() != Variable::CONST) {
1867 // Assignment to var or initializing assignment to let. 1892 // Assignment to var or initializing assignment to let.
1868 if (var->IsStackAllocated() || var->IsContextSlot()) { 1893 if (var->IsStackAllocated() || var->IsContextSlot()) {
1869 MemOperand location = VarOperand(var, ecx); 1894 MemOperand location = VarOperand(var, ecx);
1870 if (FLAG_debug_code && op == Token::INIT_LET) { 1895 if (FLAG_debug_code && op == Token::INIT_LET) {
1871 // Check for an uninitialized let binding. 1896 // Check for an uninitialized let binding.
1872 __ mov(edx, location); 1897 __ mov(edx, location);
1873 __ cmp(edx, isolate()->factory()->the_hole_value()); 1898 __ cmp(edx, isolate()->factory()->the_hole_value());
1874 __ Check(equal, "Let binding re-initialization."); 1899 __ Check(equal, "Let binding re-initialization.");
1875 } 1900 }
1876 // Perform the assignment. 1901 // Perform the assignment.
1877 __ mov(location, eax); 1902 __ mov(location, eax);
1878 if (var->IsContextSlot()) { 1903 if (var->IsContextSlot()) {
1879 __ mov(edx, eax); 1904 __ mov(edx, eax);
1880 __ RecordWrite(ecx, Context::SlotOffset(var->index()), edx, ebx); 1905 int offset = Context::SlotOffset(var->index());
1906 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
1881 } 1907 }
1882 } else { 1908 } else {
1883 ASSERT(var->IsLookupSlot()); 1909 ASSERT(var->IsLookupSlot());
1884 __ push(eax); // Value. 1910 __ push(eax); // Value.
1885 __ push(esi); // Context. 1911 __ push(esi); // Context.
1886 __ push(Immediate(var->name())); 1912 __ push(Immediate(var->name()));
1887 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 1913 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1888 __ CallRuntime(Runtime::kStoreContextSlot, 4); 1914 __ CallRuntime(Runtime::kStoreContextSlot, 4);
1889 } 1915 }
1890 } 1916 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2062 // Code common for calls using the call stub. 2088 // Code common for calls using the call stub.
2063 ZoneList<Expression*>* args = expr->arguments(); 2089 ZoneList<Expression*>* args = expr->arguments();
2064 int arg_count = args->length(); 2090 int arg_count = args->length();
2065 { PreservePositionScope scope(masm()->positions_recorder()); 2091 { PreservePositionScope scope(masm()->positions_recorder());
2066 for (int i = 0; i < arg_count; i++) { 2092 for (int i = 0; i < arg_count; i++) {
2067 VisitForStackValue(args->at(i)); 2093 VisitForStackValue(args->at(i));
2068 } 2094 }
2069 } 2095 }
2070 // Record source position for debugger. 2096 // Record source position for debugger.
2071 SetSourcePosition(expr->position()); 2097 SetSourcePosition(expr->position());
2098
2099 // Record call targets in unoptimized code, but not in the snapshot.
2100 bool record_call_target = !Serializer::enabled();
2101 if (record_call_target) {
2102 flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
2103 }
2072 CallFunctionStub stub(arg_count, flags); 2104 CallFunctionStub stub(arg_count, flags);
2073 __ CallStub(&stub); 2105 __ CallStub(&stub);
2106 if (record_call_target) {
2107 // There is a one element cache in the instruction stream.
2108 #ifdef DEBUG
2109 int return_site_offset = masm()->pc_offset();
2110 #endif
2111 Handle<Object> uninitialized =
2112 CallFunctionStub::UninitializedSentinel(isolate());
2113 Handle<JSGlobalPropertyCell> cell =
2114 isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
2115 __ test(eax, Immediate(cell));
2116 // Patching code in the stub assumes the opcode is 1 byte and there is
2117 // word for a pointer in the operand.
2118 ASSERT(masm()->pc_offset() - return_site_offset >= 1 + kPointerSize);
2119 }
2120
2074 RecordJSReturnSite(expr); 2121 RecordJSReturnSite(expr);
2075 // Restore context register. 2122 // Restore context register.
2076 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2123 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2077 2124
2078 decrement_stack_height(arg_count + 1); 2125 decrement_stack_height(arg_count + 1);
2079 context()->DropAndPlug(1, eax); 2126 context()->DropAndPlug(1, eax);
2080 } 2127 }
2081 2128
2082 2129
2083 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, 2130 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 __ LoadInstanceDescriptors(ebx, ebx); 2478 __ LoadInstanceDescriptors(ebx, ebx);
2432 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 2479 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
2433 // ebx: descriptor array 2480 // ebx: descriptor array
2434 // ecx: length of descriptor array 2481 // ecx: length of descriptor array
2435 // Calculate the end of the descriptor array. 2482 // Calculate the end of the descriptor array.
2436 STATIC_ASSERT(kSmiTag == 0); 2483 STATIC_ASSERT(kSmiTag == 0);
2437 STATIC_ASSERT(kSmiTagSize == 1); 2484 STATIC_ASSERT(kSmiTagSize == 1);
2438 STATIC_ASSERT(kPointerSize == 4); 2485 STATIC_ASSERT(kPointerSize == 4);
2439 __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); 2486 __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
2440 // Calculate location of the first key name. 2487 // Calculate location of the first key name.
2441 __ add(Operand(ebx), 2488 __ add(ebx,
2442 Immediate(FixedArray::kHeaderSize + 2489 Immediate(FixedArray::kHeaderSize +
2443 DescriptorArray::kFirstIndex * kPointerSize)); 2490 DescriptorArray::kFirstIndex * kPointerSize));
2444 // 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
2445 // symbol valueOf the result is false. 2492 // symbol valueOf the result is false.
2446 Label entry, loop; 2493 Label entry, loop;
2447 __ jmp(&entry); 2494 __ jmp(&entry);
2448 __ bind(&loop); 2495 __ bind(&loop);
2449 __ mov(edx, FieldOperand(ebx, 0)); 2496 __ mov(edx, FieldOperand(ebx, 0));
2450 __ cmp(edx, FACTORY->value_of_symbol()); 2497 __ cmp(edx, FACTORY->value_of_symbol());
2451 __ j(equal, if_false); 2498 __ j(equal, if_false);
2452 __ add(Operand(ebx), Immediate(kPointerSize)); 2499 __ add(ebx, Immediate(kPointerSize));
2453 __ bind(&entry); 2500 __ bind(&entry);
2454 __ cmp(ebx, Operand(ecx)); 2501 __ cmp(ebx, ecx);
2455 __ j(not_equal, &loop); 2502 __ j(not_equal, &loop);
2456 2503
2457 // Reload map as register ebx was used as temporary above. 2504 // Reload map as register ebx was used as temporary above.
2458 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2505 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2459 2506
2460 // 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
2461 // 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.
2462 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 2509 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
2463 __ JumpIfSmi(ecx, if_false); 2510 __ JumpIfSmi(ecx, if_false);
2464 __ 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
2584 2631
2585 Label materialize_true, materialize_false; 2632 Label materialize_true, materialize_false;
2586 Label* if_true = NULL; 2633 Label* if_true = NULL;
2587 Label* if_false = NULL; 2634 Label* if_false = NULL;
2588 Label* fall_through = NULL; 2635 Label* fall_through = NULL;
2589 context()->PrepareTest(&materialize_true, &materialize_false, 2636 context()->PrepareTest(&materialize_true, &materialize_false,
2590 &if_true, &if_false, &fall_through); 2637 &if_true, &if_false, &fall_through);
2591 2638
2592 __ pop(ebx); 2639 __ pop(ebx);
2593 decrement_stack_height(); 2640 decrement_stack_height();
2594 __ cmp(eax, Operand(ebx)); 2641 __ cmp(eax, ebx);
2595 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2642 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2596 Split(equal, if_true, if_false, fall_through); 2643 Split(equal, if_true, if_false, fall_through);
2597 2644
2598 context()->Plug(if_true, if_false); 2645 context()->Plug(if_true, if_false);
2599 } 2646 }
2600 2647
2601 2648
2602 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2649 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2603 ASSERT(args->length() == 1); 2650 ASSERT(args->length() == 1);
2604 2651
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2640 ASSERT(args->length() == 1); 2687 ASSERT(args->length() == 1);
2641 Label done, null, function, non_function_constructor; 2688 Label done, null, function, non_function_constructor;
2642 2689
2643 VisitForAccumulatorValue(args->at(0)); 2690 VisitForAccumulatorValue(args->at(0));
2644 2691
2645 // If the object is a smi, we return null. 2692 // If the object is a smi, we return null.
2646 __ JumpIfSmi(eax, &null); 2693 __ JumpIfSmi(eax, &null);
2647 2694
2648 // Check that the object is a JS object but take special care of JS 2695 // Check that the object is a JS object but take special care of JS
2649 // functions to make sure they have 'Function' as their class. 2696 // functions to make sure they have 'Function' as their class.
2697 // Assume that there are only two callable types, and one of them is at
2698 // either end of the type range for JS object types. Saves extra comparisons.
2699 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2650 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax); 2700 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax);
2651 // Map is now in eax. 2701 // Map is now in eax.
2652 __ j(below, &null); 2702 __ j(below, &null);
2703 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2704 FIRST_SPEC_OBJECT_TYPE + 1);
2705 __ j(equal, &function);
2653 2706
2654 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and 2707 __ CmpInstanceType(eax, LAST_SPEC_OBJECT_TYPE);
2655 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after 2708 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2656 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. 2709 LAST_SPEC_OBJECT_TYPE - 1);
2657 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); 2710 __ j(equal, &function);
2658 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == 2711 // Assume that there is no larger type.
2659 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); 2712 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
2660 __ CmpInstanceType(eax, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
2661 __ j(above_equal, &function);
2662 2713
2663 // Check if the constructor in the map is a function. 2714 // Check if the constructor in the map is a JS function.
2664 __ mov(eax, FieldOperand(eax, Map::kConstructorOffset)); 2715 __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2665 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2716 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2666 __ j(not_equal, &non_function_constructor); 2717 __ j(not_equal, &non_function_constructor);
2667 2718
2668 // eax now contains the constructor function. Grab the 2719 // eax now contains the constructor function. Grab the
2669 // instance class name from there. 2720 // instance class name from there.
2670 __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 2721 __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2671 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); 2722 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2672 __ jmp(&done); 2723 __ jmp(&done);
2673 2724
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2734 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 2785 __ CallCFunction(ExternalReference::random_uint32_function(isolate()),
2735 1); 2786 1);
2736 2787
2737 // 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
2738 // by computing: 2789 // by computing:
2739 // ( 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)).
2740 // This is implemented on both SSE2 and FPU. 2791 // This is implemented on both SSE2 and FPU.
2741 if (CpuFeatures::IsSupported(SSE2)) { 2792 if (CpuFeatures::IsSupported(SSE2)) {
2742 CpuFeatures::Scope fscope(SSE2); 2793 CpuFeatures::Scope fscope(SSE2);
2743 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2794 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2744 __ movd(xmm1, Operand(ebx)); 2795 __ movd(xmm1, ebx);
2745 __ movd(xmm0, Operand(eax)); 2796 __ movd(xmm0, eax);
2746 __ cvtss2sd(xmm1, xmm1); 2797 __ cvtss2sd(xmm1, xmm1);
2747 __ xorps(xmm0, xmm1); 2798 __ xorps(xmm0, xmm1);
2748 __ subsd(xmm0, xmm1); 2799 __ subsd(xmm0, xmm1);
2749 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); 2800 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2750 } else { 2801 } else {
2751 // 0x4130000000000000 is 1.0 x 2^20 as a double. 2802 // 0x4130000000000000 is 1.0 x 2^20 as a double.
2752 __ mov(FieldOperand(edi, HeapNumber::kExponentOffset), 2803 __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2753 Immediate(0x41300000)); 2804 Immediate(0x41300000));
2754 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax); 2805 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2755 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2806 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2836 Label done; 2887 Label done;
2837 // If the object is a smi, return the value. 2888 // If the object is a smi, return the value.
2838 __ JumpIfSmi(ebx, &done, Label::kNear); 2889 __ JumpIfSmi(ebx, &done, Label::kNear);
2839 2890
2840 // If the object is not a value type, return the value. 2891 // If the object is not a value type, return the value.
2841 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 2892 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2842 __ j(not_equal, &done, Label::kNear); 2893 __ j(not_equal, &done, Label::kNear);
2843 2894
2844 // Store the value. 2895 // Store the value.
2845 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 2896 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2897
2846 // Update the write barrier. Save the value as it will be 2898 // Update the write barrier. Save the value as it will be
2847 // overwritten by the write barrier code and is needed afterward. 2899 // overwritten by the write barrier code and is needed afterward.
2848 __ mov(edx, eax); 2900 __ mov(edx, eax);
2849 __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); 2901 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
2850 2902
2851 __ bind(&done); 2903 __ bind(&done);
2852 context()->Plug(eax); 2904 context()->Plug(eax);
2853 } 2905 }
2854 2906
2855 2907
2856 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2908 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2857 ASSERT_EQ(args->length(), 1); 2909 ASSERT_EQ(args->length(), 1);
2858 2910
2859 // Load the argument on the stack and call the stub. 2911 // Load the argument on the stack and call the stub.
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
3112 // Check the object's elements are in fast case and writable. 3164 // Check the object's elements are in fast case and writable.
3113 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); 3165 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
3114 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), 3166 __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
3115 Immediate(isolate()->factory()->fixed_array_map())); 3167 Immediate(isolate()->factory()->fixed_array_map()));
3116 __ j(not_equal, &slow_case); 3168 __ j(not_equal, &slow_case);
3117 3169
3118 // Check that both indices are smis. 3170 // Check that both indices are smis.
3119 __ mov(index_1, Operand(esp, 1 * kPointerSize)); 3171 __ mov(index_1, Operand(esp, 1 * kPointerSize));
3120 __ mov(index_2, Operand(esp, 0)); 3172 __ mov(index_2, Operand(esp, 0));
3121 __ mov(temp, index_1); 3173 __ mov(temp, index_1);
3122 __ or_(temp, Operand(index_2)); 3174 __ or_(temp, index_2);
3123 __ JumpIfNotSmi(temp, &slow_case); 3175 __ JumpIfNotSmi(temp, &slow_case);
3124 3176
3125 // Check that both indices are valid. 3177 // Check that both indices are valid.
3126 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset)); 3178 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
3127 __ cmp(temp, Operand(index_1)); 3179 __ cmp(temp, index_1);
3128 __ j(below_equal, &slow_case); 3180 __ j(below_equal, &slow_case);
3129 __ cmp(temp, Operand(index_2)); 3181 __ cmp(temp, index_2);
3130 __ j(below_equal, &slow_case); 3182 __ j(below_equal, &slow_case);
3131 3183
3132 // Bring addresses into index1 and index2. 3184 // Bring addresses into index1 and index2.
3133 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); 3185 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
3134 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); 3186 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
3135 3187
3136 // Swap elements. Use object and temp as scratch registers. 3188 // Swap elements. Use object and temp as scratch registers.
3137 __ mov(object, Operand(index_1, 0)); 3189 __ mov(object, Operand(index_1, 0));
3138 __ mov(temp, Operand(index_2, 0)); 3190 __ mov(temp, Operand(index_2, 0));
3139 __ mov(Operand(index_2, 0), object); 3191 __ mov(Operand(index_2, 0), object);
3140 __ mov(Operand(index_1, 0), temp); 3192 __ mov(Operand(index_1, 0), temp);
3141 3193
3142 Label new_space; 3194 Label no_remembered_set;
3143 __ InNewSpace(elements, temp, equal, &new_space); 3195 __ CheckPageFlag(elements,
3196 temp,
3197 1 << MemoryChunk::SCAN_ON_SCAVENGE,
3198 not_zero,
3199 &no_remembered_set,
3200 Label::kNear);
3201 // Possible optimization: do a check that both values are Smis
3202 // (or them and test against Smi mask.)
3144 3203
3145 __ mov(object, elements); 3204 // We are swapping two objects in an array and the incremental marker never
3146 __ RecordWriteHelper(object, index_1, temp); 3205 // pauses in the middle of scanning a single object. Therefore the
3147 __ RecordWriteHelper(elements, index_2, temp); 3206 // incremental marker is not disturbed, so we don't need to call the
3207 // RecordWrite stub that notifies the incremental marker.
3208 __ RememberedSetHelper(elements,
3209 index_1,
3210 temp,
3211 kDontSaveFPRegs,
3212 MacroAssembler::kFallThroughAtEnd);
3213 __ RememberedSetHelper(elements,
3214 index_2,
3215 temp,
3216 kDontSaveFPRegs,
3217 MacroAssembler::kFallThroughAtEnd);
3148 3218
3149 __ bind(&new_space); 3219 __ bind(&no_remembered_set);
3220
3150 // We are done. Drop elements from the stack, and return undefined. 3221 // We are done. Drop elements from the stack, and return undefined.
3151 __ add(Operand(esp), Immediate(3 * kPointerSize)); 3222 __ add(esp, Immediate(3 * kPointerSize));
3152 __ mov(eax, isolate()->factory()->undefined_value()); 3223 __ mov(eax, isolate()->factory()->undefined_value());
3153 __ jmp(&done); 3224 __ jmp(&done);
3154 3225
3155 __ bind(&slow_case); 3226 __ bind(&slow_case);
3156 __ CallRuntime(Runtime::kSwapElements, 3); 3227 __ CallRuntime(Runtime::kSwapElements, 3);
3157 3228
3158 __ bind(&done); 3229 __ bind(&done);
3159 decrement_stack_height(3); 3230 decrement_stack_height(3);
3160 context()->Plug(eax); 3231 context()->Plug(eax);
3161 } 3232 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3214 3285
3215 Register right = eax; 3286 Register right = eax;
3216 Register left = ebx; 3287 Register left = ebx;
3217 Register tmp = ecx; 3288 Register tmp = ecx;
3218 3289
3219 VisitForStackValue(args->at(0)); 3290 VisitForStackValue(args->at(0));
3220 VisitForAccumulatorValue(args->at(1)); 3291 VisitForAccumulatorValue(args->at(1));
3221 __ pop(left); 3292 __ pop(left);
3222 3293
3223 Label done, fail, ok; 3294 Label done, fail, ok;
3224 __ cmp(left, Operand(right)); 3295 __ cmp(left, right);
3225 __ j(equal, &ok); 3296 __ j(equal, &ok);
3226 // Fail if either is a non-HeapObject. 3297 // Fail if either is a non-HeapObject.
3227 __ mov(tmp, left); 3298 __ mov(tmp, left);
3228 __ and_(Operand(tmp), right); 3299 __ and_(tmp, right);
3229 __ JumpIfSmi(tmp, &fail); 3300 __ JumpIfSmi(tmp, &fail);
3230 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset)); 3301 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
3231 __ CmpInstanceType(tmp, JS_REGEXP_TYPE); 3302 __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
3232 __ j(not_equal, &fail); 3303 __ j(not_equal, &fail);
3233 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); 3304 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3234 __ j(not_equal, &fail); 3305 __ j(not_equal, &fail);
3235 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 3306 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3236 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 3307 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3237 __ j(equal, &ok); 3308 __ j(equal, &ok);
3238 __ bind(&fail); 3309 __ bind(&fail);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3309 3380
3310 Register scratch = ebx; 3381 Register scratch = ebx;
3311 3382
3312 Register array_length = edi; 3383 Register array_length = edi;
3313 Register result_pos = no_reg; // Will be edi. 3384 Register result_pos = no_reg; // Will be edi.
3314 3385
3315 // Separator operand is already pushed. 3386 // Separator operand is already pushed.
3316 Operand separator_operand = Operand(esp, 2 * kPointerSize); 3387 Operand separator_operand = Operand(esp, 2 * kPointerSize);
3317 Operand result_operand = Operand(esp, 1 * kPointerSize); 3388 Operand result_operand = Operand(esp, 1 * kPointerSize);
3318 Operand array_length_operand = Operand(esp, 0); 3389 Operand array_length_operand = Operand(esp, 0);
3319 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 3390 __ sub(esp, Immediate(2 * kPointerSize));
3320 __ cld(); 3391 __ cld();
3321 // Check that the array is a JSArray 3392 // Check that the array is a JSArray
3322 __ JumpIfSmi(array, &bailout); 3393 __ JumpIfSmi(array, &bailout);
3323 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3394 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3324 __ j(not_equal, &bailout); 3395 __ j(not_equal, &bailout);
3325 3396
3326 // Check that the array has fast elements. 3397 // Check that the array has fast elements.
3327 __ CheckFastElements(scratch, &bailout); 3398 __ CheckFastElements(scratch, &bailout);
3328 3399
3329 // 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
3345 3416
3346 3417
3347 // Check that all array elements are sequential ASCII strings, and 3418 // Check that all array elements are sequential ASCII strings, and
3348 // accumulate the sum of their lengths, as a smi-encoded value. 3419 // accumulate the sum of their lengths, as a smi-encoded value.
3349 __ Set(index, Immediate(0)); 3420 __ Set(index, Immediate(0));
3350 __ Set(string_length, Immediate(0)); 3421 __ Set(string_length, Immediate(0));
3351 // Loop condition: while (index < length). 3422 // Loop condition: while (index < length).
3352 // Live loop registers: index, array_length, string, 3423 // Live loop registers: index, array_length, string,
3353 // scratch, string_length, elements. 3424 // scratch, string_length, elements.
3354 if (FLAG_debug_code) { 3425 if (FLAG_debug_code) {
3355 __ cmp(index, Operand(array_length)); 3426 __ cmp(index, array_length);
3356 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin"); 3427 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3357 } 3428 }
3358 __ bind(&loop); 3429 __ bind(&loop);
3359 __ mov(string, FieldOperand(elements, 3430 __ mov(string, FieldOperand(elements,
3360 index, 3431 index,
3361 times_pointer_size, 3432 times_pointer_size,
3362 FixedArray::kHeaderSize)); 3433 FixedArray::kHeaderSize));
3363 __ JumpIfSmi(string, &bailout); 3434 __ JumpIfSmi(string, &bailout);
3364 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3435 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3365 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3436 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3366 __ and_(scratch, Immediate( 3437 __ and_(scratch, Immediate(
3367 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3438 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3368 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3439 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3369 __ j(not_equal, &bailout); 3440 __ j(not_equal, &bailout);
3370 __ add(string_length, 3441 __ add(string_length,
3371 FieldOperand(string, SeqAsciiString::kLengthOffset)); 3442 FieldOperand(string, SeqAsciiString::kLengthOffset));
3372 __ j(overflow, &bailout); 3443 __ j(overflow, &bailout);
3373 __ add(Operand(index), Immediate(1)); 3444 __ add(index, Immediate(1));
3374 __ cmp(index, Operand(array_length)); 3445 __ cmp(index, array_length);
3375 __ j(less, &loop); 3446 __ j(less, &loop);
3376 3447
3377 // If array_length is 1, return elements[0], a string. 3448 // If array_length is 1, return elements[0], a string.
3378 __ cmp(array_length, 1); 3449 __ cmp(array_length, 1);
3379 __ j(not_equal, &not_size_one_array); 3450 __ j(not_equal, &not_size_one_array);
3380 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); 3451 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3381 __ mov(result_operand, scratch); 3452 __ mov(result_operand, scratch);
3382 __ jmp(&done); 3453 __ jmp(&done);
3383 3454
3384 __ bind(&not_size_one_array); 3455 __ bind(&not_size_one_array);
(...skipping 13 matching lines...) Expand all
3398 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3469 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3399 __ and_(scratch, Immediate( 3470 __ and_(scratch, Immediate(
3400 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3471 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3401 __ cmp(scratch, ASCII_STRING_TYPE); 3472 __ cmp(scratch, ASCII_STRING_TYPE);
3402 __ j(not_equal, &bailout); 3473 __ j(not_equal, &bailout);
3403 3474
3404 // Add (separator length times array_length) - separator length 3475 // Add (separator length times array_length) - separator length
3405 // to string_length. 3476 // to string_length.
3406 __ mov(scratch, separator_operand); 3477 __ mov(scratch, separator_operand);
3407 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); 3478 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3408 __ sub(string_length, Operand(scratch)); // May be negative, temporarily. 3479 __ sub(string_length, scratch); // May be negative, temporarily.
3409 __ imul(scratch, array_length_operand); 3480 __ imul(scratch, array_length_operand);
3410 __ j(overflow, &bailout); 3481 __ j(overflow, &bailout);
3411 __ add(string_length, Operand(scratch)); 3482 __ add(string_length, scratch);
3412 __ j(overflow, &bailout); 3483 __ j(overflow, &bailout);
3413 3484
3414 __ shr(string_length, 1); 3485 __ shr(string_length, 1);
3415 // Live registers and stack values: 3486 // Live registers and stack values:
3416 // string_length 3487 // string_length
3417 // elements 3488 // elements
3418 __ AllocateAsciiString(result_pos, string_length, scratch, 3489 __ AllocateAsciiString(result_pos, string_length, scratch,
3419 index, string, &bailout); 3490 index, string, &bailout);
3420 __ mov(result_operand, result_pos); 3491 __ mov(result_operand, result_pos);
3421 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); 3492 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
(...skipping 20 matching lines...) Expand all
3442 // Get string = array[index]. 3513 // Get string = array[index].
3443 __ mov(string, FieldOperand(elements, index, 3514 __ mov(string, FieldOperand(elements, index,
3444 times_pointer_size, 3515 times_pointer_size,
3445 FixedArray::kHeaderSize)); 3516 FixedArray::kHeaderSize));
3446 __ mov(string_length, 3517 __ mov(string_length,
3447 FieldOperand(string, String::kLengthOffset)); 3518 FieldOperand(string, String::kLengthOffset));
3448 __ shr(string_length, 1); 3519 __ shr(string_length, 1);
3449 __ lea(string, 3520 __ lea(string,
3450 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3521 FieldOperand(string, SeqAsciiString::kHeaderSize));
3451 __ CopyBytes(string, result_pos, string_length, scratch); 3522 __ CopyBytes(string, result_pos, string_length, scratch);
3452 __ add(Operand(index), Immediate(1)); 3523 __ add(index, Immediate(1));
3453 __ bind(&loop_1_condition); 3524 __ bind(&loop_1_condition);
3454 __ cmp(index, array_length_operand); 3525 __ cmp(index, array_length_operand);
3455 __ j(less, &loop_1); // End while (index < length). 3526 __ j(less, &loop_1); // End while (index < length).
3456 __ jmp(&done); 3527 __ jmp(&done);
3457 3528
3458 3529
3459 3530
3460 // One-character separator case 3531 // One-character separator case
3461 __ bind(&one_char_separator); 3532 __ bind(&one_char_separator);
3462 // Replace separator with its ascii character value. 3533 // Replace separator with its ascii character value.
(...skipping 20 matching lines...) Expand all
3483 // Get string = array[index]. 3554 // Get string = array[index].
3484 __ mov(string, FieldOperand(elements, index, 3555 __ mov(string, FieldOperand(elements, index,
3485 times_pointer_size, 3556 times_pointer_size,
3486 FixedArray::kHeaderSize)); 3557 FixedArray::kHeaderSize));
3487 __ mov(string_length, 3558 __ mov(string_length,
3488 FieldOperand(string, String::kLengthOffset)); 3559 FieldOperand(string, String::kLengthOffset));
3489 __ shr(string_length, 1); 3560 __ shr(string_length, 1);
3490 __ lea(string, 3561 __ lea(string,
3491 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3562 FieldOperand(string, SeqAsciiString::kHeaderSize));
3492 __ CopyBytes(string, result_pos, string_length, scratch); 3563 __ CopyBytes(string, result_pos, string_length, scratch);
3493 __ add(Operand(index), Immediate(1)); 3564 __ add(index, Immediate(1));
3494 3565
3495 __ cmp(index, array_length_operand); 3566 __ cmp(index, array_length_operand);
3496 __ j(less, &loop_2); // End while (index < length). 3567 __ j(less, &loop_2); // End while (index < length).
3497 __ jmp(&done); 3568 __ jmp(&done);
3498 3569
3499 3570
3500 // Long separator case (separator is more than one character). 3571 // Long separator case (separator is more than one character).
3501 __ bind(&long_separator); 3572 __ bind(&long_separator);
3502 3573
3503 __ Set(index, Immediate(0)); 3574 __ Set(index, Immediate(0));
(...skipping 20 matching lines...) Expand all
3524 // Get string = array[index]. 3595 // Get string = array[index].
3525 __ mov(string, FieldOperand(elements, index, 3596 __ mov(string, FieldOperand(elements, index,
3526 times_pointer_size, 3597 times_pointer_size,
3527 FixedArray::kHeaderSize)); 3598 FixedArray::kHeaderSize));
3528 __ mov(string_length, 3599 __ mov(string_length,
3529 FieldOperand(string, String::kLengthOffset)); 3600 FieldOperand(string, String::kLengthOffset));
3530 __ shr(string_length, 1); 3601 __ shr(string_length, 1);
3531 __ lea(string, 3602 __ lea(string,
3532 FieldOperand(string, SeqAsciiString::kHeaderSize)); 3603 FieldOperand(string, SeqAsciiString::kHeaderSize));
3533 __ CopyBytes(string, result_pos, string_length, scratch); 3604 __ CopyBytes(string, result_pos, string_length, scratch);
3534 __ add(Operand(index), Immediate(1)); 3605 __ add(index, Immediate(1));
3535 3606
3536 __ cmp(index, array_length_operand); 3607 __ cmp(index, array_length_operand);
3537 __ j(less, &loop_3); // End while (index < length). 3608 __ j(less, &loop_3); // End while (index < length).
3538 __ jmp(&done); 3609 __ jmp(&done);
3539 3610
3540 3611
3541 __ bind(&bailout); 3612 __ bind(&bailout);
3542 __ mov(result_operand, isolate()->factory()->undefined_value()); 3613 __ mov(result_operand, isolate()->factory()->undefined_value());
3543 __ bind(&done); 3614 __ bind(&done);
3544 __ mov(eax, result_operand); 3615 __ mov(eax, result_operand);
3545 // Drop temp values from the stack, and restore context register. 3616 // Drop temp values from the stack, and restore context register.
3546 __ add(Operand(esp), Immediate(3 * kPointerSize)); 3617 __ add(esp, Immediate(3 * kPointerSize));
3547 3618
3548 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3619 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3549 decrement_stack_height(); 3620 decrement_stack_height();
3550 context()->Plug(eax); 3621 context()->Plug(eax);
3551 } 3622 }
3552 3623
3553 3624
3554 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3625 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3555 Handle<String> name = expr->name(); 3626 Handle<String> name = expr->name();
3556 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
3816 } 3887 }
3817 } 3888 }
3818 } 3889 }
3819 3890
3820 // Inline smi case if we are in a loop. 3891 // Inline smi case if we are in a loop.
3821 Label done, stub_call; 3892 Label done, stub_call;
3822 JumpPatchSite patch_site(masm_); 3893 JumpPatchSite patch_site(masm_);
3823 3894
3824 if (ShouldInlineSmiCase(expr->op())) { 3895 if (ShouldInlineSmiCase(expr->op())) {
3825 if (expr->op() == Token::INC) { 3896 if (expr->op() == Token::INC) {
3826 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3897 __ add(eax, Immediate(Smi::FromInt(1)));
3827 } else { 3898 } else {
3828 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3899 __ sub(eax, Immediate(Smi::FromInt(1)));
3829 } 3900 }
3830 __ j(overflow, &stub_call, Label::kNear); 3901 __ j(overflow, &stub_call, Label::kNear);
3831 // 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
3832 // the first smi check before calling ToNumber. 3903 // the first smi check before calling ToNumber.
3833 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear); 3904 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear);
3834 3905
3835 __ bind(&stub_call); 3906 __ bind(&stub_call);
3836 // Call stub. Undo operation first. 3907 // Call stub. Undo operation first.
3837 if (expr->op() == Token::INC) { 3908 if (expr->op() == Token::INC) {
3838 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3909 __ sub(eax, Immediate(Smi::FromInt(1)));
3839 } else { 3910 } else {
3840 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3911 __ add(eax, Immediate(Smi::FromInt(1)));
3841 } 3912 }
3842 } 3913 }
3843 3914
3844 // Record position before stub call. 3915 // Record position before stub call.
3845 SetSourcePosition(expr->position()); 3916 SetSourcePosition(expr->position());
3846 3917
3847 // Call stub for +1/-1. 3918 // Call stub for +1/-1.
3848 __ mov(edx, eax); 3919 __ mov(edx, eax);
3849 __ mov(eax, Immediate(Smi::FromInt(1))); 3920 __ mov(eax, Immediate(Smi::FromInt(1)));
3850 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 3921 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
3949 4020
3950 context()->Plug(eax); 4021 context()->Plug(eax);
3951 } else { 4022 } else {
3952 // This expression cannot throw a reference error at the top level. 4023 // This expression cannot throw a reference error at the top level.
3953 VisitInCurrentContext(expr); 4024 VisitInCurrentContext(expr);
3954 } 4025 }
3955 } 4026 }
3956 4027
3957 4028
3958 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 4029 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3959 Handle<String> check, 4030 Handle<String> check) {
3960 Label* if_true, 4031 Label materialize_true, materialize_false;
3961 Label* if_false, 4032 Label* if_true = NULL;
3962 Label* fall_through) { 4033 Label* if_false = NULL;
4034 Label* fall_through = NULL;
4035 context()->PrepareTest(&materialize_true, &materialize_false,
4036 &if_true, &if_false, &fall_through);
4037
3963 { AccumulatorValueContext context(this); 4038 { AccumulatorValueContext context(this);
3964 VisitForTypeofValue(expr); 4039 VisitForTypeofValue(expr);
3965 } 4040 }
3966 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4041 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3967 4042
3968 if (check->Equals(isolate()->heap()->number_symbol())) { 4043 if (check->Equals(isolate()->heap()->number_symbol())) {
3969 __ JumpIfSmi(eax, if_true); 4044 __ JumpIfSmi(eax, if_true);
3970 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 4045 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3971 isolate()->factory()->heap_number_map()); 4046 isolate()->factory()->heap_number_map());
3972 Split(equal, if_true, if_false, fall_through); 4047 Split(equal, if_true, if_false, fall_through);
(...skipping 18 matching lines...) Expand all
3991 __ cmp(eax, isolate()->factory()->undefined_value()); 4066 __ cmp(eax, isolate()->factory()->undefined_value());
3992 __ j(equal, if_true); 4067 __ j(equal, if_true);
3993 __ JumpIfSmi(eax, if_false); 4068 __ JumpIfSmi(eax, if_false);
3994 // Check for undetectable objects => true. 4069 // Check for undetectable objects => true.
3995 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 4070 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
3996 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 4071 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
3997 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 4072 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
3998 Split(not_zero, if_true, if_false, fall_through); 4073 Split(not_zero, if_true, if_false, fall_through);
3999 } else if (check->Equals(isolate()->heap()->function_symbol())) { 4074 } else if (check->Equals(isolate()->heap()->function_symbol())) {
4000 __ JumpIfSmi(eax, if_false); 4075 __ JumpIfSmi(eax, if_false);
4001 __ CmpObjectType(eax, FIRST_CALLABLE_SPEC_OBJECT_TYPE, edx); 4076 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4002 Split(above_equal, if_true, if_false, fall_through); 4077 __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
4078 __ j(equal, if_true);
4079 __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
4080 Split(equal, if_true, if_false, fall_through);
4003 } else if (check->Equals(isolate()->heap()->object_symbol())) { 4081 } else if (check->Equals(isolate()->heap()->object_symbol())) {
4004 __ JumpIfSmi(eax, if_false); 4082 __ JumpIfSmi(eax, if_false);
4005 if (!FLAG_harmony_typeof) { 4083 if (!FLAG_harmony_typeof) {
4006 __ cmp(eax, isolate()->factory()->null_value()); 4084 __ cmp(eax, isolate()->factory()->null_value());
4007 __ j(equal, if_true); 4085 __ j(equal, if_true);
4008 } 4086 }
4009 __ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx); 4087 __ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
4010 __ j(below, if_false); 4088 __ j(below, if_false);
4011 __ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4089 __ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4012 __ j(above, if_false); 4090 __ j(above, if_false);
4013 // Check for undetectable objects => false. 4091 // Check for undetectable objects => false.
4014 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), 4092 __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4015 1 << Map::kIsUndetectable); 4093 1 << Map::kIsUndetectable);
4016 Split(zero, if_true, if_false, fall_through); 4094 Split(zero, if_true, if_false, fall_through);
4017 } else { 4095 } else {
4018 if (if_false != fall_through) __ jmp(if_false); 4096 if (if_false != fall_through) __ jmp(if_false);
4019 } 4097 }
4020 } 4098 context()->Plug(if_true, if_false);
4021
4022
4023 void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr,
4024 Label* if_true,
4025 Label* if_false,
4026 Label* fall_through) {
4027 VisitForAccumulatorValue(expr);
4028 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4029
4030 __ cmp(eax, isolate()->factory()->undefined_value());
4031 Split(equal, if_true, if_false, fall_through);
4032 } 4099 }
4033 4100
4034 4101
4035 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4102 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4036 Comment cmnt(masm_, "[ CompareOperation"); 4103 Comment cmnt(masm_, "[ CompareOperation");
4037 SetSourcePosition(expr->position()); 4104 SetSourcePosition(expr->position());
4038 4105
4106 // First we try a fast inlined version of the compare when one of
4107 // the operands is a literal.
4108 if (TryLiteralCompare(expr)) return;
4109
4039 // Always perform the comparison for its control flow. Pack the result 4110 // Always perform the comparison for its control flow. Pack the result
4040 // into the expression's context after the comparison is performed. 4111 // into the expression's context after the comparison is performed.
4041
4042 Label materialize_true, materialize_false; 4112 Label materialize_true, materialize_false;
4043 Label* if_true = NULL; 4113 Label* if_true = NULL;
4044 Label* if_false = NULL; 4114 Label* if_false = NULL;
4045 Label* fall_through = NULL; 4115 Label* fall_through = NULL;
4046 context()->PrepareTest(&materialize_true, &materialize_false, 4116 context()->PrepareTest(&materialize_true, &materialize_false,
4047 &if_true, &if_false, &fall_through); 4117 &if_true, &if_false, &fall_through);
4048 4118
4049 // First we try a fast inlined version of the compare when one of
4050 // the operands is a literal.
4051 if (TryLiteralCompare(expr, if_true, if_false, fall_through)) {
4052 context()->Plug(if_true, if_false);
4053 return;
4054 }
4055
4056 Token::Value op = expr->op(); 4119 Token::Value op = expr->op();
4057 VisitForStackValue(expr->left()); 4120 VisitForStackValue(expr->left());
4058 switch (expr->op()) { 4121 switch (op) {
4059 case Token::IN: 4122 case Token::IN:
4060 VisitForStackValue(expr->right()); 4123 VisitForStackValue(expr->right());
4061 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4124 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4062 decrement_stack_height(2); 4125 decrement_stack_height(2);
4063 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4126 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4064 __ cmp(eax, isolate()->factory()->true_value()); 4127 __ cmp(eax, isolate()->factory()->true_value());
4065 Split(equal, if_true, if_false, fall_through); 4128 Split(equal, if_true, if_false, fall_through);
4066 break; 4129 break;
4067 4130
4068 case Token::INSTANCEOF: { 4131 case Token::INSTANCEOF: {
4069 VisitForStackValue(expr->right()); 4132 VisitForStackValue(expr->right());
4070 InstanceofStub stub(InstanceofStub::kNoFlags); 4133 InstanceofStub stub(InstanceofStub::kNoFlags);
4071 __ CallStub(&stub); 4134 __ CallStub(&stub);
4072 decrement_stack_height(2); 4135 decrement_stack_height(2);
4073 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4136 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4074 __ test(eax, Operand(eax)); 4137 __ test(eax, eax);
4075 // The stub returns 0 for true. 4138 // The stub returns 0 for true.
4076 Split(zero, if_true, if_false, fall_through); 4139 Split(zero, if_true, if_false, fall_through);
4077 break; 4140 break;
4078 } 4141 }
4079 4142
4080 default: { 4143 default: {
4081 VisitForAccumulatorValue(expr->right()); 4144 VisitForAccumulatorValue(expr->right());
4082 Condition cc = no_condition; 4145 Condition cc = no_condition;
4083 bool strict = false;
4084 switch (op) { 4146 switch (op) {
4085 case Token::EQ_STRICT: 4147 case Token::EQ_STRICT:
4086 strict = true;
4087 // Fall through
4088 case Token::EQ: 4148 case Token::EQ:
4089 cc = equal; 4149 cc = equal;
4090 __ pop(edx); 4150 __ pop(edx);
4091 break; 4151 break;
4092 case Token::LT: 4152 case Token::LT:
4093 cc = less; 4153 cc = less;
4094 __ pop(edx); 4154 __ pop(edx);
4095 break; 4155 break;
4096 case Token::GT: 4156 case Token::GT:
4097 // Reverse left and right sizes to obtain ECMA-262 conversion order. 4157 // Reverse left and right sizes to obtain ECMA-262 conversion order.
(...skipping 15 matching lines...) Expand all
4113 case Token::INSTANCEOF: 4173 case Token::INSTANCEOF:
4114 default: 4174 default:
4115 UNREACHABLE(); 4175 UNREACHABLE();
4116 } 4176 }
4117 decrement_stack_height(); 4177 decrement_stack_height();
4118 4178
4119 bool inline_smi_code = ShouldInlineSmiCase(op); 4179 bool inline_smi_code = ShouldInlineSmiCase(op);
4120 JumpPatchSite patch_site(masm_); 4180 JumpPatchSite patch_site(masm_);
4121 if (inline_smi_code) { 4181 if (inline_smi_code) {
4122 Label slow_case; 4182 Label slow_case;
4123 __ mov(ecx, Operand(edx)); 4183 __ mov(ecx, edx);
4124 __ or_(ecx, Operand(eax)); 4184 __ or_(ecx, eax);
4125 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4185 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4126 __ cmp(edx, Operand(eax)); 4186 __ cmp(edx, eax);
4127 Split(cc, if_true, if_false, NULL); 4187 Split(cc, if_true, if_false, NULL);
4128 __ bind(&slow_case); 4188 __ bind(&slow_case);
4129 } 4189 }
4130 4190
4131 // Record position and call the compare IC. 4191 // Record position and call the compare IC.
4132 SetSourcePosition(expr->position()); 4192 SetSourcePosition(expr->position());
4133 Handle<Code> ic = CompareIC::GetUninitialized(op); 4193 Handle<Code> ic = CompareIC::GetUninitialized(op);
4134 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 4194 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4135 patch_site.EmitPatchInfo(); 4195 patch_site.EmitPatchInfo();
4136 4196
4137 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4197 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4138 __ test(eax, Operand(eax)); 4198 __ test(eax, eax);
4139 Split(cc, if_true, if_false, fall_through); 4199 Split(cc, if_true, if_false, fall_through);
4140 } 4200 }
4141 } 4201 }
4142 4202
4143 // Convert the result of the comparison into one expected for this 4203 // Convert the result of the comparison into one expected for this
4144 // expression's context. 4204 // expression's context.
4145 context()->Plug(if_true, if_false); 4205 context()->Plug(if_true, if_false);
4146 } 4206 }
4147 4207
4148 4208
4149 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 4209 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4210 Expression* sub_expr,
4211 NilValue nil) {
4150 Label materialize_true, materialize_false; 4212 Label materialize_true, materialize_false;
4151 Label* if_true = NULL; 4213 Label* if_true = NULL;
4152 Label* if_false = NULL; 4214 Label* if_false = NULL;
4153 Label* fall_through = NULL; 4215 Label* fall_through = NULL;
4154 context()->PrepareTest(&materialize_true, &materialize_false, 4216 context()->PrepareTest(&materialize_true, &materialize_false,
4155 &if_true, &if_false, &fall_through); 4217 &if_true, &if_false, &fall_through);
4156 4218
4157 VisitForAccumulatorValue(expr->expression()); 4219 VisitForAccumulatorValue(sub_expr);
4158 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4220 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4159 4221 Handle<Object> nil_value = nil == kNullValue ?
4160 __ cmp(eax, isolate()->factory()->null_value()); 4222 isolate()->factory()->null_value() :
4161 if (expr->is_strict()) { 4223 isolate()->factory()->undefined_value();
4224 __ cmp(eax, nil_value);
4225 if (expr->op() == Token::EQ_STRICT) {
4162 Split(equal, if_true, if_false, fall_through); 4226 Split(equal, if_true, if_false, fall_through);
4163 } else { 4227 } else {
4228 Handle<Object> other_nil_value = nil == kNullValue ?
4229 isolate()->factory()->undefined_value() :
4230 isolate()->factory()->null_value();
4164 __ j(equal, if_true); 4231 __ j(equal, if_true);
4165 __ cmp(eax, isolate()->factory()->undefined_value()); 4232 __ cmp(eax, other_nil_value);
4166 __ j(equal, if_true); 4233 __ j(equal, if_true);
4167 __ JumpIfSmi(eax, if_false); 4234 __ JumpIfSmi(eax, if_false);
4168 // It can be an undetectable object. 4235 // It can be an undetectable object.
4169 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 4236 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
4170 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); 4237 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset));
4171 __ test(edx, Immediate(1 << Map::kIsUndetectable)); 4238 __ test(edx, Immediate(1 << Map::kIsUndetectable));
4172 Split(not_zero, if_true, if_false, fall_through); 4239 Split(not_zero, if_true, if_false, fall_through);
4173 } 4240 }
4174 context()->Plug(if_true, if_false); 4241 context()->Plug(if_true, if_false);
4175 } 4242 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
4222 } 4289 }
4223 4290
4224 4291
4225 // ---------------------------------------------------------------------------- 4292 // ----------------------------------------------------------------------------
4226 // Non-local control flow support. 4293 // Non-local control flow support.
4227 4294
4228 void FullCodeGenerator::EnterFinallyBlock() { 4295 void FullCodeGenerator::EnterFinallyBlock() {
4229 // Cook return address on top of stack (smi encoded Code* delta) 4296 // Cook return address on top of stack (smi encoded Code* delta)
4230 ASSERT(!result_register().is(edx)); 4297 ASSERT(!result_register().is(edx));
4231 __ pop(edx); 4298 __ pop(edx);
4232 __ sub(Operand(edx), Immediate(masm_->CodeObject())); 4299 __ sub(edx, Immediate(masm_->CodeObject()));
4233 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4300 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4234 STATIC_ASSERT(kSmiTag == 0); 4301 STATIC_ASSERT(kSmiTag == 0);
4235 __ SmiTag(edx); 4302 __ SmiTag(edx);
4236 __ push(edx); 4303 __ push(edx);
4237 // Store result register while executing finally block. 4304 // Store result register while executing finally block.
4238 __ push(result_register()); 4305 __ push(result_register());
4239 } 4306 }
4240 4307
4241 4308
4242 void FullCodeGenerator::ExitFinallyBlock() { 4309 void FullCodeGenerator::ExitFinallyBlock() {
4243 ASSERT(!result_register().is(edx)); 4310 ASSERT(!result_register().is(edx));
4244 __ pop(result_register()); 4311 __ pop(result_register());
4245 // Uncook return address. 4312 // Uncook return address.
4246 __ pop(edx); 4313 __ pop(edx);
4247 __ SmiUntag(edx); 4314 __ SmiUntag(edx);
4248 __ add(Operand(edx), Immediate(masm_->CodeObject())); 4315 __ add(edx, Immediate(masm_->CodeObject()));
4249 __ jmp(Operand(edx)); 4316 __ jmp(edx);
4250 } 4317 }
4251 4318
4252 4319
4253 #undef __ 4320 #undef __
4254 4321
4255 #define __ ACCESS_MASM(masm()) 4322 #define __ ACCESS_MASM(masm())
4256 4323
4257 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4324 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4258 int* stack_depth, 4325 int* stack_depth,
4259 int* context_length) { 4326 int* context_length) {
(...skipping 16 matching lines...) Expand all
4276 *context_length = 0; 4343 *context_length = 0;
4277 return previous_; 4344 return previous_;
4278 } 4345 }
4279 4346
4280 4347
4281 #undef __ 4348 #undef __
4282 4349
4283 } } // namespace v8::internal 4350 } } // namespace v8::internal
4284 4351
4285 #endif // V8_TARGET_ARCH_IA32 4352 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698