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

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

Issue 6588047: Version 3.1.7... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/frames-x64.cc ('k') | src/x64/ic-x64.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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 // stack frame was an arguments adapter frame. 200 // stack frame was an arguments adapter frame.
201 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 201 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
202 __ CallStub(&stub); 202 __ CallStub(&stub);
203 // Store new arguments object in both "arguments" and ".arguments" slots. 203 // Store new arguments object in both "arguments" and ".arguments" slots.
204 __ movq(rcx, rax); 204 __ movq(rcx, rax);
205 Move(arguments->AsSlot(), rax, rbx, rdx); 205 Move(arguments->AsSlot(), rax, rbx, rdx);
206 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); 206 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
207 Move(dot_arguments_slot, rcx, rbx, rdx); 207 Move(dot_arguments_slot, rcx, rbx, rdx);
208 } 208 }
209 209
210 { Comment cmnt(masm_, "[ Declarations");
211 // For named function expressions, declare the function name as a
212 // constant.
213 if (scope()->is_function_scope() && scope()->function() != NULL) {
214 EmitDeclaration(scope()->function(), Variable::CONST, NULL);
215 }
216 // Visit all the explicit declarations unless there is an illegal
217 // redeclaration.
218 if (scope()->HasIllegalRedeclaration()) {
219 scope()->VisitIllegalRedeclaration(this);
220 } else {
221 VisitDeclarations(scope()->declarations());
222 }
223 }
224
225 if (FLAG_trace) { 210 if (FLAG_trace) {
226 __ CallRuntime(Runtime::kTraceEnter, 0); 211 __ CallRuntime(Runtime::kTraceEnter, 0);
227 } 212 }
228 213
229 { Comment cmnt(masm_, "[ Stack check"); 214 // Visit the declarations and body unless there is an illegal
230 PrepareForBailout(info->function(), NO_REGISTERS); 215 // redeclaration.
231 NearLabel ok; 216 if (scope()->HasIllegalRedeclaration()) {
232 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 217 Comment cmnt(masm_, "[ Declarations");
233 __ j(above_equal, &ok); 218 scope()->VisitIllegalRedeclaration(this);
234 StackCheckStub stub; 219 } else {
235 __ CallStub(&stub); 220 { Comment cmnt(masm_, "[ Declarations");
236 __ bind(&ok); 221 // For named function expressions, declare the function name as a
222 // constant.
223 if (scope()->is_function_scope() && scope()->function() != NULL) {
224 EmitDeclaration(scope()->function(), Variable::CONST, NULL);
225 }
226 VisitDeclarations(scope()->declarations());
227 }
228
229 { Comment cmnt(masm_, "[ Stack check");
230 PrepareForBailout(info->function(), NO_REGISTERS);
231 NearLabel ok;
232 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
233 __ j(above_equal, &ok);
234 StackCheckStub stub;
235 __ CallStub(&stub);
236 __ bind(&ok);
237 }
238
239 { Comment cmnt(masm_, "[ Body");
240 ASSERT(loop_depth() == 0);
241 VisitStatements(function()->body());
242 ASSERT(loop_depth() == 0);
243 }
237 } 244 }
238 245
239 { Comment cmnt(masm_, "[ Body"); 246 // Always emit a 'return undefined' in case control fell off the end of
240 ASSERT(loop_depth() == 0); 247 // the body.
241 VisitStatements(function()->body());
242 ASSERT(loop_depth() == 0);
243 }
244
245 { Comment cmnt(masm_, "[ return <undefined>;"); 248 { Comment cmnt(masm_, "[ return <undefined>;");
246 // Emit a 'return undefined' in case control fell off the end of the body.
247 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 249 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
248 EmitReturnSequence(); 250 EmitReturnSequence();
249 } 251 }
250 } 252 }
251 253
252 254
253 void FullCodeGenerator::ClearAccumulator() { 255 void FullCodeGenerator::ClearAccumulator() {
254 __ Set(rax, 0); 256 __ Set(rax, 0);
255 } 257 }
256 258
257 259
258 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { 260 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
259 Comment cmnt(masm_, "[ Stack check"); 261 Comment cmnt(masm_, "[ Stack check");
260 NearLabel ok; 262 NearLabel ok;
261 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 263 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
262 __ j(above_equal, &ok); 264 __ j(above_equal, &ok);
263 StackCheckStub stub; 265 StackCheckStub stub;
264 __ CallStub(&stub); 266 __ CallStub(&stub);
265 // Record a mapping of this PC offset to the OSR id. This is used to find 267 // Record a mapping of this PC offset to the OSR id. This is used to find
266 // the AST id from the unoptimized code in order to use it as a key into 268 // the AST id from the unoptimized code in order to use it as a key into
267 // the deoptimization input data found in the optimized code. 269 // the deoptimization input data found in the optimized code.
268 RecordStackCheck(stmt->OsrEntryId()); 270 RecordStackCheck(stmt->OsrEntryId());
269 271
272 // Loop stack checks can be patched to perform on-stack replacement. In
273 // order to decide whether or not to perform OSR we embed the loop depth
274 // in a test instruction after the call so we can extract it from the OSR
275 // builtin.
276 ASSERT(loop_depth() > 0);
277 __ testl(rax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
278
270 __ bind(&ok); 279 __ bind(&ok);
271 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 280 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
272 // Record a mapping of the OSR id to this PC. This is used if the OSR 281 // Record a mapping of the OSR id to this PC. This is used if the OSR
273 // entry becomes the target of a bailout. We don't expect it to be, but 282 // entry becomes the target of a bailout. We don't expect it to be, but
274 // we want it to work if it is. 283 // we want it to work if it is.
275 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 284 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
276 } 285 }
277 286
278 287
279 void FullCodeGenerator::EmitReturnSequence() { 288 void FullCodeGenerator::EmitReturnSequence() {
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 void FullCodeGenerator::DoTest(Label* if_true, 545 void FullCodeGenerator::DoTest(Label* if_true,
537 Label* if_false, 546 Label* if_false,
538 Label* fall_through) { 547 Label* fall_through) {
539 // Emit the inlined tests assumed by the stub. 548 // Emit the inlined tests assumed by the stub.
540 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 549 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
541 __ j(equal, if_false); 550 __ j(equal, if_false);
542 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 551 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
543 __ j(equal, if_true); 552 __ j(equal, if_true);
544 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 553 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
545 __ j(equal, if_false); 554 __ j(equal, if_false);
546 ASSERT_EQ(0, kSmiTag); 555 STATIC_ASSERT(kSmiTag == 0);
547 __ SmiCompare(result_register(), Smi::FromInt(0)); 556 __ SmiCompare(result_register(), Smi::FromInt(0));
548 __ j(equal, if_false); 557 __ j(equal, if_false);
549 Condition is_smi = masm_->CheckSmi(result_register()); 558 Condition is_smi = masm_->CheckSmi(result_register());
550 __ j(is_smi, if_true); 559 __ j(is_smi, if_true);
551 560
552 // Call the ToBoolean stub for all other cases. 561 // Call the ToBoolean stub for all other cases.
553 ToBooleanStub stub; 562 ToBooleanStub stub;
554 __ push(result_register()); 563 __ push(result_register());
555 __ CallStub(&stub); 564 __ CallStub(&stub);
556 __ testq(rax, rax); 565 __ testq(rax, rax);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 Label loop, exit; 853 Label loop, exit;
845 ForIn loop_statement(this, stmt); 854 ForIn loop_statement(this, stmt);
846 increment_loop_depth(); 855 increment_loop_depth();
847 856
848 // Get the object to enumerate over. Both SpiderMonkey and JSC 857 // Get the object to enumerate over. Both SpiderMonkey and JSC
849 // ignore null and undefined in contrast to the specification; see 858 // ignore null and undefined in contrast to the specification; see
850 // ECMA-262 section 12.6.4. 859 // ECMA-262 section 12.6.4.
851 VisitForAccumulatorValue(stmt->enumerable()); 860 VisitForAccumulatorValue(stmt->enumerable());
852 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 861 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
853 __ j(equal, &exit); 862 __ j(equal, &exit);
854 __ CompareRoot(rax, Heap::kNullValueRootIndex); 863 Register null_value = rdi;
864 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
865 __ cmpq(rax, null_value);
855 __ j(equal, &exit); 866 __ j(equal, &exit);
856 867
857 // Convert the object to a JS object. 868 // Convert the object to a JS object.
858 Label convert, done_convert; 869 Label convert, done_convert;
859 __ JumpIfSmi(rax, &convert); 870 __ JumpIfSmi(rax, &convert);
860 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 871 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
861 __ j(above_equal, &done_convert); 872 __ j(above_equal, &done_convert);
862 __ bind(&convert); 873 __ bind(&convert);
863 __ push(rax); 874 __ push(rax);
864 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 875 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
865 __ bind(&done_convert); 876 __ bind(&done_convert);
866 __ push(rax); 877 __ push(rax);
867 878
868 // BUG(867): Check cache validity in generated code. This is a fast 879 // Check cache validity in generated code. This is a fast case for
869 // case for the JSObject::IsSimpleEnum cache validity checks. If we 880 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
870 // cannot guarantee cache validity, call the runtime system to check 881 // guarantee cache validity, call the runtime system to check cache
871 // cache validity or get the property names in a fixed array. 882 // validity or get the property names in a fixed array.
883 Label next, call_runtime;
884 Register empty_fixed_array_value = r8;
885 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
886 Register empty_descriptor_array_value = r9;
887 __ LoadRoot(empty_descriptor_array_value,
888 Heap::kEmptyDescriptorArrayRootIndex);
889 __ movq(rcx, rax);
890 __ bind(&next);
891
892 // Check that there are no elements. Register rcx contains the
893 // current JS object we've reached through the prototype chain.
894 __ cmpq(empty_fixed_array_value,
895 FieldOperand(rcx, JSObject::kElementsOffset));
896 __ j(not_equal, &call_runtime);
897
898 // Check that instance descriptors are not empty so that we can
899 // check for an enum cache. Leave the map in rbx for the subsequent
900 // prototype load.
901 __ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
902 __ movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOffset));
903 __ cmpq(rdx, empty_descriptor_array_value);
904 __ j(equal, &call_runtime);
905
906 // Check that there is an enum cache in the non-empty instance
907 // descriptors (rdx). This is the case if the next enumeration
908 // index field does not contain a smi.
909 __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset));
910 __ JumpIfSmi(rdx, &call_runtime);
911
912 // For all objects but the receiver, check that the cache is empty.
913 NearLabel check_prototype;
914 __ cmpq(rcx, rax);
915 __ j(equal, &check_prototype);
916 __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset));
917 __ cmpq(rdx, empty_fixed_array_value);
918 __ j(not_equal, &call_runtime);
919
920 // Load the prototype from the map and loop if non-null.
921 __ bind(&check_prototype);
922 __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
923 __ cmpq(rcx, null_value);
924 __ j(not_equal, &next);
925
926 // The enum cache is valid. Load the map of the object being
927 // iterated over and use the cache for the iteration.
928 NearLabel use_cache;
929 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
930 __ jmp(&use_cache);
872 931
873 // Get the set of properties to enumerate. 932 // Get the set of properties to enumerate.
933 __ bind(&call_runtime);
874 __ push(rax); // Duplicate the enumerable object on the stack. 934 __ push(rax); // Duplicate the enumerable object on the stack.
875 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 935 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
876 936
877 // If we got a map from the runtime call, we can do a fast 937 // If we got a map from the runtime call, we can do a fast
878 // modification check. Otherwise, we got a fixed array, and we have 938 // modification check. Otherwise, we got a fixed array, and we have
879 // to do a slow check. 939 // to do a slow check.
880 NearLabel fixed_array; 940 NearLabel fixed_array;
881 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 941 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
882 Heap::kMetaMapRootIndex); 942 Heap::kMetaMapRootIndex);
883 __ j(not_equal, &fixed_array); 943 __ j(not_equal, &fixed_array);
884 944
885 // We got a map in register rax. Get the enumeration cache from it. 945 // We got a map in register rax. Get the enumeration cache from it.
946 __ bind(&use_cache);
886 __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset)); 947 __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset));
887 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); 948 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
888 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 949 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
889 950
890 // Setup the four remaining stack slots. 951 // Setup the four remaining stack slots.
891 __ push(rax); // Map. 952 __ push(rax); // Map.
892 __ push(rdx); // Enumeration cache. 953 __ push(rdx); // Enumeration cache.
893 __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 954 __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
894 __ push(rax); // Enumeration cache length (as smi). 955 __ push(rax); // Enumeration cache length (as smi).
895 __ Push(Smi::FromInt(0)); // Initial index. 956 __ Push(Smi::FromInt(0)); // Initial index.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 1025
965 // Exit and decrement the loop depth. 1026 // Exit and decrement the loop depth.
966 __ bind(&exit); 1027 __ bind(&exit);
967 decrement_loop_depth(); 1028 decrement_loop_depth();
968 } 1029 }
969 1030
970 1031
971 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 1032 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
972 bool pretenure) { 1033 bool pretenure) {
973 // Use the fast case closure allocation code that allocates in new 1034 // Use the fast case closure allocation code that allocates in new
974 // space for nested functions that don't need literals cloning. 1035 // space for nested functions that don't need literals cloning. If
975 if (scope()->is_function_scope() && 1036 // we're running with the --always-opt or the --prepare-always-opt
1037 // flag, we need to use the runtime function so that the new function
1038 // we are creating here gets a chance to have its code optimized and
1039 // doesn't just get a copy of the existing unoptimized code.
1040 if (!FLAG_always_opt &&
1041 !FLAG_prepare_always_opt &&
1042 scope()->is_function_scope() &&
976 info->num_literals() == 0 && 1043 info->num_literals() == 0 &&
977 !pretenure) { 1044 !pretenure) {
978 FastNewClosureStub stub; 1045 FastNewClosureStub stub;
979 __ Push(info); 1046 __ Push(info);
980 __ CallStub(&stub); 1047 __ CallStub(&stub);
981 } else { 1048 } else {
982 __ push(rsi); 1049 __ push(rsi);
983 __ Push(info); 1050 __ Push(info);
984 __ Push(pretenure ? Factory::true_value() : Factory::false_value()); 1051 __ Push(pretenure ? Factory::true_value() : Factory::false_value());
985 __ CallRuntime(Runtime::kNewClosure, 3); 1052 __ CallRuntime(Runtime::kNewClosure, 3);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 } 1142 }
1076 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 1143 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX));
1077 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset)); 1144 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
1078 // Walk the rest of the chain without clobbering rsi. 1145 // Walk the rest of the chain without clobbering rsi.
1079 context = temp; 1146 context = temp;
1080 } 1147 }
1081 } 1148 }
1082 // Check that last extension is NULL. 1149 // Check that last extension is NULL.
1083 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 1150 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1084 __ j(not_equal, slow); 1151 __ j(not_equal, slow);
1085 __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX)); 1152
1086 return ContextOperand(temp, slot->index()); 1153 // This function is used only for loads, not stores, so it's safe to
1154 // return an rsi-based operand (the write barrier cannot be allowed to
1155 // destroy the rsi register).
1156 return ContextOperand(context, slot->index());
1087 } 1157 }
1088 1158
1089 1159
1090 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( 1160 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
1091 Slot* slot, 1161 Slot* slot,
1092 TypeofState typeof_state, 1162 TypeofState typeof_state,
1093 Label* slow, 1163 Label* slow,
1094 Label* done) { 1164 Label* done) {
1095 // Generate fast-case code for variables that might be shadowed by 1165 // Generate fast-case code for variables that might be shadowed by
1096 // eval-introduced variables. Eval is used a lot without 1166 // eval-introduced variables. Eval is used a lot without
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 // Assignment to a global variable. Use inline caching for the 1793 // Assignment to a global variable. Use inline caching for the
1724 // assignment. Right-hand-side value is passed in rax, variable name in 1794 // assignment. Right-hand-side value is passed in rax, variable name in
1725 // rcx, and the global object on the stack. 1795 // rcx, and the global object on the stack.
1726 __ Move(rcx, var->name()); 1796 __ Move(rcx, var->name());
1727 __ movq(rdx, GlobalObjectOperand()); 1797 __ movq(rdx, GlobalObjectOperand());
1728 Handle<Code> ic(Builtins::builtin(is_strict() 1798 Handle<Code> ic(Builtins::builtin(is_strict()
1729 ? Builtins::StoreIC_Initialize_Strict 1799 ? Builtins::StoreIC_Initialize_Strict
1730 : Builtins::StoreIC_Initialize)); 1800 : Builtins::StoreIC_Initialize));
1731 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 1801 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1732 1802
1733 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1803 } else if (op == Token::INIT_CONST) {
1734 // Perform the assignment for non-const variables and for initialization 1804 // Like var declarations, const declarations are hoisted to function
1735 // of const variables. Const assignments are simply skipped. 1805 // scope. However, unlike var initializers, const initializers are able
1736 Label done; 1806 // to drill a hole to that function context, even from inside a 'with'
1807 // context. We thus bypass the normal static scope lookup.
1808 Slot* slot = var->AsSlot();
1809 Label skip;
1810 switch (slot->type()) {
1811 case Slot::PARAMETER:
1812 // No const parameters.
1813 UNREACHABLE();
1814 break;
1815 case Slot::LOCAL:
1816 __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1817 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1818 __ j(not_equal, &skip);
1819 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1820 break;
1821 case Slot::CONTEXT: {
1822 __ movq(rcx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
1823 __ movq(rdx, ContextOperand(rcx, slot->index()));
1824 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1825 __ j(not_equal, &skip);
1826 __ movq(ContextOperand(rcx, slot->index()), rax);
1827 int offset = Context::SlotOffset(slot->index());
1828 __ movq(rdx, rax); // Preserve the stored value in eax.
1829 __ RecordWrite(rcx, offset, rdx, rbx);
1830 break;
1831 }
1832 case Slot::LOOKUP:
1833 __ push(rax);
1834 __ push(rsi);
1835 __ Push(var->name());
1836 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1837 break;
1838 }
1839 __ bind(&skip);
1840
1841 } else if (var->mode() != Variable::CONST) {
1842 // Perform the assignment for non-const variables. Const assignments
1843 // are simply skipped.
1737 Slot* slot = var->AsSlot(); 1844 Slot* slot = var->AsSlot();
1738 switch (slot->type()) { 1845 switch (slot->type()) {
1739 case Slot::PARAMETER: 1846 case Slot::PARAMETER:
1740 case Slot::LOCAL: 1847 case Slot::LOCAL:
1741 if (op == Token::INIT_CONST) {
1742 // Detect const reinitialization by checking for the hole value.
1743 __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1744 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1745 __ j(not_equal, &done);
1746 }
1747 // Perform the assignment. 1848 // Perform the assignment.
1748 __ movq(Operand(rbp, SlotOffset(slot)), rax); 1849 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1749 break; 1850 break;
1750 1851
1751 case Slot::CONTEXT: { 1852 case Slot::CONTEXT: {
1752 MemOperand target = EmitSlotSearch(slot, rcx); 1853 MemOperand target = EmitSlotSearch(slot, rcx);
1753 if (op == Token::INIT_CONST) {
1754 // Detect const reinitialization by checking for the hole value.
1755 __ movq(rdx, target);
1756 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1757 __ j(not_equal, &done);
1758 }
1759 // Perform the assignment and issue the write barrier. 1854 // Perform the assignment and issue the write barrier.
1760 __ movq(target, rax); 1855 __ movq(target, rax);
1761 // The value of the assignment is in rax. RecordWrite clobbers its 1856 // The value of the assignment is in rax. RecordWrite clobbers its
1762 // register arguments. 1857 // register arguments.
1763 __ movq(rdx, rax); 1858 __ movq(rdx, rax);
1764 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1859 int offset = Context::SlotOffset(slot->index());
1765 __ RecordWrite(rcx, offset, rdx, rbx); 1860 __ RecordWrite(rcx, offset, rdx, rbx);
1766 break; 1861 break;
1767 } 1862 }
1768 1863
1769 case Slot::LOOKUP: 1864 case Slot::LOOKUP:
1770 // Call the runtime for the assignment. The runtime will ignore 1865 // Call the runtime for the assignment.
1771 // const reinitialization.
1772 __ push(rax); // Value. 1866 __ push(rax); // Value.
1773 __ push(rsi); // Context. 1867 __ push(rsi); // Context.
1774 __ Push(var->name()); 1868 __ Push(var->name());
1775 if (op == Token::INIT_CONST) { 1869 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1776 // The runtime will ignore const redeclaration.
1777 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1778 } else {
1779 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1780 }
1781 break; 1870 break;
1782 } 1871 }
1783 __ bind(&done);
1784 } 1872 }
1785 } 1873 }
1786 1874
1787 1875
1788 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1876 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1789 // Assignment to a property, using a named store IC. 1877 // Assignment to a property, using a named store IC.
1790 Property* prop = expr->target()->AsProperty(); 1878 Property* prop = expr->target()->AsProperty();
1791 ASSERT(prop != NULL); 1879 ASSERT(prop != NULL);
1792 ASSERT(prop->key()->AsLiteral() != NULL); 1880 ASSERT(prop->key()->AsLiteral() != NULL);
1793 1881
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 VisitForStackValue(args->at(1)); 2886 VisitForStackValue(args->at(1));
2799 2887
2800 StringCompareStub stub; 2888 StringCompareStub stub;
2801 __ CallStub(&stub); 2889 __ CallStub(&stub);
2802 context()->Plug(rax); 2890 context()->Plug(rax);
2803 } 2891 }
2804 2892
2805 2893
2806 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2894 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2807 // Load the argument on the stack and call the stub. 2895 // Load the argument on the stack and call the stub.
2808 TranscendentalCacheStub stub(TranscendentalCache::SIN); 2896 TranscendentalCacheStub stub(TranscendentalCache::SIN,
2897 TranscendentalCacheStub::TAGGED);
2809 ASSERT(args->length() == 1); 2898 ASSERT(args->length() == 1);
2810 VisitForStackValue(args->at(0)); 2899 VisitForStackValue(args->at(0));
2811 __ CallStub(&stub); 2900 __ CallStub(&stub);
2812 context()->Plug(rax); 2901 context()->Plug(rax);
2813 } 2902 }
2814 2903
2815 2904
2816 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2905 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2817 // Load the argument on the stack and call the stub. 2906 // Load the argument on the stack and call the stub.
2818 TranscendentalCacheStub stub(TranscendentalCache::COS); 2907 TranscendentalCacheStub stub(TranscendentalCache::COS,
2908 TranscendentalCacheStub::TAGGED);
2819 ASSERT(args->length() == 1); 2909 ASSERT(args->length() == 1);
2820 VisitForStackValue(args->at(0)); 2910 VisitForStackValue(args->at(0));
2821 __ CallStub(&stub); 2911 __ CallStub(&stub);
2822 context()->Plug(rax); 2912 context()->Plug(rax);
2823 } 2913 }
2824 2914
2825 2915
2826 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 2916 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
2827 // Load the argument on the stack and call the stub. 2917 // Load the argument on the stack and call the stub.
2828 TranscendentalCacheStub stub(TranscendentalCache::LOG); 2918 TranscendentalCacheStub stub(TranscendentalCache::LOG,
2919 TranscendentalCacheStub::TAGGED);
2829 ASSERT(args->length() == 1); 2920 ASSERT(args->length() == 1);
2830 VisitForStackValue(args->at(0)); 2921 VisitForStackValue(args->at(0));
2831 __ CallStub(&stub); 2922 __ CallStub(&stub);
2832 context()->Plug(rax); 2923 context()->Plug(rax);
2833 } 2924 }
2834 2925
2835 2926
2836 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2927 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2837 // Load the argument on the stack and call the runtime function. 2928 // Load the argument on the stack and call the runtime function.
2838 ASSERT(args->length() == 1); 2929 ASSERT(args->length() == 1);
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2993 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3084 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2994 __ j(zero, if_true); 3085 __ j(zero, if_true);
2995 __ jmp(if_false); 3086 __ jmp(if_false);
2996 3087
2997 context()->Plug(if_true, if_false); 3088 context()->Plug(if_true, if_false);
2998 } 3089 }
2999 3090
3000 3091
3001 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3092 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
3002 ASSERT(args->length() == 1); 3093 ASSERT(args->length() == 1);
3094 VisitForAccumulatorValue(args->at(0));
3003 3095
3004 VisitForAccumulatorValue(args->at(0)); 3096 if (FLAG_debug_code) {
3097 __ AbortIfNotString(rax);
3098 }
3005 3099
3006 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 3100 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
3007 ASSERT(String::kHashShift >= kSmiTagSize); 3101 ASSERT(String::kHashShift >= kSmiTagSize);
3008 __ IndexFromHash(rax, rax); 3102 __ IndexFromHash(rax, rax);
3009 3103
3010 context()->Plug(rax); 3104 context()->Plug(rax);
3011 } 3105 }
3012 3106
3013 3107
3014 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3108 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
3708 __ nop(); // Signals no inlined code. 3802 __ nop(); // Signals no inlined code.
3709 break; 3803 break;
3710 default: 3804 default:
3711 // Do nothing. 3805 // Do nothing.
3712 break; 3806 break;
3713 } 3807 }
3714 } 3808 }
3715 3809
3716 3810
3717 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { 3811 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
3812 switch (ic->kind()) {
3813 case Code::LOAD_IC:
3814 __ IncrementCounter(&Counters::named_load_full, 1);
3815 break;
3816 case Code::KEYED_LOAD_IC:
3817 __ IncrementCounter(&Counters::keyed_load_full, 1);
3818 break;
3819 case Code::STORE_IC:
3820 __ IncrementCounter(&Counters::named_store_full, 1);
3821 break;
3822 case Code::KEYED_STORE_IC:
3823 __ IncrementCounter(&Counters::keyed_store_full, 1);
3824 default:
3825 break;
3826 }
3827
3718 __ call(ic, RelocInfo::CODE_TARGET); 3828 __ call(ic, RelocInfo::CODE_TARGET);
3719 if (patch_site != NULL && patch_site->is_bound()) { 3829 if (patch_site != NULL && patch_site->is_bound()) {
3720 patch_site->EmitPatchInfo(); 3830 patch_site->EmitPatchInfo();
3721 } else { 3831 } else {
3722 __ nop(); // Signals no inlined code. 3832 __ nop(); // Signals no inlined code.
3723 } 3833 }
3724 } 3834 }
3725 3835
3726 3836
3727 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3837 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3768 __ ret(0); 3878 __ ret(0);
3769 } 3879 }
3770 3880
3771 3881
3772 #undef __ 3882 #undef __
3773 3883
3774 3884
3775 } } // namespace v8::internal 3885 } } // namespace v8::internal
3776 3886
3777 #endif // V8_TARGET_ARCH_X64 3887 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/frames-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698