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

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

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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/deoptimizer-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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 Comment cmnt(masm_, "[ Declarations"); 247 Comment cmnt(masm_, "[ Declarations");
248 scope()->VisitIllegalRedeclaration(this); 248 scope()->VisitIllegalRedeclaration(this);
249 249
250 } else { 250 } else {
251 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 251 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
252 { Comment cmnt(masm_, "[ Declarations"); 252 { Comment cmnt(masm_, "[ Declarations");
253 // For named function expressions, declare the function name as a 253 // For named function expressions, declare the function name as a
254 // constant. 254 // constant.
255 if (scope()->is_function_scope() && scope()->function() != NULL) { 255 if (scope()->is_function_scope() && scope()->function() != NULL) {
256 int ignored = 0; 256 int ignored = 0;
257 EmitDeclaration(scope()->function(), CONST, NULL, &ignored); 257 VariableProxy* proxy = scope()->function();
258 ASSERT(proxy->var()->mode() == CONST ||
259 proxy->var()->mode() == CONST_HARMONY);
260 EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored);
258 } 261 }
259 VisitDeclarations(scope()->declarations()); 262 VisitDeclarations(scope()->declarations());
260 } 263 }
261 264
262 { Comment cmnt(masm_, "[ Stack check"); 265 { Comment cmnt(masm_, "[ Stack check");
263 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 266 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
264 Label ok; 267 Label ok;
265 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 268 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
266 __ j(above_equal, &ok, Label::kNear); 269 __ j(above_equal, &ok, Label::kNear);
267 StackCheckStub stub; 270 StackCheckStub stub;
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 680
678 681
679 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 682 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
680 VariableMode mode, 683 VariableMode mode,
681 FunctionLiteral* function, 684 FunctionLiteral* function,
682 int* global_count) { 685 int* global_count) {
683 // If it was not possible to allocate the variable at compile time, we 686 // If it was not possible to allocate the variable at compile time, we
684 // need to "declare" it at runtime to make sure it actually exists in the 687 // need to "declare" it at runtime to make sure it actually exists in the
685 // local context. 688 // local context.
686 Variable* variable = proxy->var(); 689 Variable* variable = proxy->var();
690 bool binding_needs_init =
691 mode == CONST || mode == CONST_HARMONY || mode == LET;
687 switch (variable->location()) { 692 switch (variable->location()) {
688 case Variable::UNALLOCATED: 693 case Variable::UNALLOCATED:
689 ++(*global_count); 694 ++(*global_count);
690 break; 695 break;
691 696
692 case Variable::PARAMETER: 697 case Variable::PARAMETER:
693 case Variable::LOCAL: 698 case Variable::LOCAL:
694 if (function != NULL) { 699 if (function != NULL) {
695 Comment cmnt(masm_, "[ Declaration"); 700 Comment cmnt(masm_, "[ Declaration");
696 VisitForAccumulatorValue(function); 701 VisitForAccumulatorValue(function);
697 __ movq(StackOperand(variable), result_register()); 702 __ movq(StackOperand(variable), result_register());
698 } else if (mode == CONST || mode == LET) { 703 } else if (binding_needs_init) {
699 Comment cmnt(masm_, "[ Declaration"); 704 Comment cmnt(masm_, "[ Declaration");
700 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 705 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
701 __ movq(StackOperand(variable), kScratchRegister); 706 __ movq(StackOperand(variable), kScratchRegister);
702 } 707 }
703 break; 708 break;
704 709
705 case Variable::CONTEXT: 710 case Variable::CONTEXT:
706 // The variable in the decl always resides in the current function 711 // The variable in the decl always resides in the current function
707 // context. 712 // context.
708 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 713 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
(...skipping 12 matching lines...) Expand all
721 int offset = Context::SlotOffset(variable->index()); 726 int offset = Context::SlotOffset(variable->index());
722 // We know that we have written a function, which is not a smi. 727 // We know that we have written a function, which is not a smi.
723 __ RecordWriteContextSlot(rsi, 728 __ RecordWriteContextSlot(rsi,
724 offset, 729 offset,
725 result_register(), 730 result_register(),
726 rcx, 731 rcx,
727 kDontSaveFPRegs, 732 kDontSaveFPRegs,
728 EMIT_REMEMBERED_SET, 733 EMIT_REMEMBERED_SET,
729 OMIT_SMI_CHECK); 734 OMIT_SMI_CHECK);
730 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 735 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
731 } else if (mode == CONST || mode == LET) { 736 } else if (binding_needs_init) {
732 Comment cmnt(masm_, "[ Declaration"); 737 Comment cmnt(masm_, "[ Declaration");
733 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 738 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
734 __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); 739 __ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
735 // No write barrier since the hole value is in old space. 740 // No write barrier since the hole value is in old space.
736 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 741 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
737 } 742 }
738 break; 743 break;
739 744
740 case Variable::LOOKUP: { 745 case Variable::LOOKUP: {
741 Comment cmnt(masm_, "[ Declaration"); 746 Comment cmnt(masm_, "[ Declaration");
742 __ push(rsi); 747 __ push(rsi);
743 __ Push(variable->name()); 748 __ Push(variable->name());
744 // Declaration nodes are always introduced in one of three modes. 749 // Declaration nodes are always introduced in one of four modes.
745 ASSERT(mode == VAR || mode == CONST || mode == LET); 750 ASSERT(mode == VAR ||
746 PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE; 751 mode == CONST ||
752 mode == CONST_HARMONY ||
753 mode == LET);
754 PropertyAttributes attr =
755 (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE;
747 __ Push(Smi::FromInt(attr)); 756 __ Push(Smi::FromInt(attr));
748 // Push initial value, if any. 757 // Push initial value, if any.
749 // Note: For variables we must not push an initial value (such as 758 // Note: For variables we must not push an initial value (such as
750 // 'undefined') because we may have a (legal) redeclaration and we 759 // 'undefined') because we may have a (legal) redeclaration and we
751 // must not destroy the current value. 760 // must not destroy the current value.
752 if (function != NULL) { 761 if (function != NULL) {
753 VisitForStackValue(function); 762 VisitForStackValue(function);
754 } else if (mode == CONST || mode == LET) { 763 } else if (binding_needs_init) {
755 __ PushRoot(Heap::kTheHoleValueRootIndex); 764 __ PushRoot(Heap::kTheHoleValueRootIndex);
756 } else { 765 } else {
757 __ Push(Smi::FromInt(0)); // Indicates no initial value. 766 __ Push(Smi::FromInt(0)); // Indicates no initial value.
758 } 767 }
759 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 768 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
760 break; 769 break;
761 } 770 }
762 } 771 }
763 } 772 }
764 773
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 Label convert, done_convert; 892 Label convert, done_convert;
884 __ JumpIfSmi(rax, &convert); 893 __ JumpIfSmi(rax, &convert);
885 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 894 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
886 __ j(above_equal, &done_convert); 895 __ j(above_equal, &done_convert);
887 __ bind(&convert); 896 __ bind(&convert);
888 __ push(rax); 897 __ push(rax);
889 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 898 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
890 __ bind(&done_convert); 899 __ bind(&done_convert);
891 __ push(rax); 900 __ push(rax);
892 901
902 // Check for proxies.
903 Label call_runtime;
904 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
905 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
906 __ j(below_equal, &call_runtime);
907
893 // Check cache validity in generated code. This is a fast case for 908 // Check cache validity in generated code. This is a fast case for
894 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 909 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
895 // guarantee cache validity, call the runtime system to check cache 910 // guarantee cache validity, call the runtime system to check cache
896 // validity or get the property names in a fixed array. 911 // validity or get the property names in a fixed array.
897 Label next, call_runtime; 912 Label next;
898 Register empty_fixed_array_value = r8; 913 Register empty_fixed_array_value = r8;
899 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); 914 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
900 Register empty_descriptor_array_value = r9; 915 Register empty_descriptor_array_value = r9;
901 __ LoadRoot(empty_descriptor_array_value, 916 __ LoadRoot(empty_descriptor_array_value,
902 Heap::kEmptyDescriptorArrayRootIndex); 917 Heap::kEmptyDescriptorArrayRootIndex);
903 __ movq(rcx, rax); 918 __ movq(rcx, rax);
904 __ bind(&next); 919 __ bind(&next);
905 920
906 // Check that there are no elements. Register rcx contains the 921 // Check that there are no elements. Register rcx contains the
907 // current JS object we've reached through the prototype chain. 922 // current JS object we've reached through the prototype chain.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 978
964 // Setup the four remaining stack slots. 979 // Setup the four remaining stack slots.
965 __ push(rax); // Map. 980 __ push(rax); // Map.
966 __ push(rdx); // Enumeration cache. 981 __ push(rdx); // Enumeration cache.
967 __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 982 __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
968 __ push(rax); // Enumeration cache length (as smi). 983 __ push(rax); // Enumeration cache length (as smi).
969 __ Push(Smi::FromInt(0)); // Initial index. 984 __ Push(Smi::FromInt(0)); // Initial index.
970 __ jmp(&loop); 985 __ jmp(&loop);
971 986
972 // We got a fixed array in register rax. Iterate through that. 987 // We got a fixed array in register rax. Iterate through that.
988 Label non_proxy;
973 __ bind(&fixed_array); 989 __ bind(&fixed_array);
974 __ Push(Smi::FromInt(0)); // Map (0) - force slow check. 990 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
975 __ push(rax); 991 __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
992 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
993 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
994 __ j(above, &non_proxy);
995 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy
996 __ bind(&non_proxy);
997 __ push(rbx); // Smi
998 __ push(rax); // Array
976 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 999 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
977 __ push(rax); // Fixed array length (as smi). 1000 __ push(rax); // Fixed array length (as smi).
978 __ Push(Smi::FromInt(0)); // Initial index. 1001 __ Push(Smi::FromInt(0)); // Initial index.
979 1002
980 // Generate code for doing the condition check. 1003 // Generate code for doing the condition check.
981 __ bind(&loop); 1004 __ bind(&loop);
982 __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 1005 __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
983 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 1006 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
984 __ j(above_equal, loop_statement.break_label()); 1007 __ j(above_equal, loop_statement.break_label());
985 1008
986 // Get the current entry of the array into register rbx. 1009 // Get the current entry of the array into register rbx.
987 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 1010 __ movq(rbx, Operand(rsp, 2 * kPointerSize));
988 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 1011 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
989 __ movq(rbx, FieldOperand(rbx, 1012 __ movq(rbx, FieldOperand(rbx,
990 index.reg, 1013 index.reg,
991 index.scale, 1014 index.scale,
992 FixedArray::kHeaderSize)); 1015 FixedArray::kHeaderSize));
993 1016
994 // Get the expected map from the stack or a zero map in the 1017 // Get the expected map from the stack or a smi in the
995 // permanent slow case into register rdx. 1018 // permanent slow case into register rdx.
996 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 1019 __ movq(rdx, Operand(rsp, 3 * kPointerSize));
997 1020
998 // Check if the expected map still matches that of the enumerable. 1021 // Check if the expected map still matches that of the enumerable.
999 // If not, we have to filter the key. 1022 // If not, we may have to filter the key.
1000 Label update_each; 1023 Label update_each;
1001 __ movq(rcx, Operand(rsp, 4 * kPointerSize)); 1024 __ movq(rcx, Operand(rsp, 4 * kPointerSize));
1002 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 1025 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1003 __ j(equal, &update_each, Label::kNear); 1026 __ j(equal, &update_each, Label::kNear);
1004 1027
1028 // For proxies, no filtering is done.
1029 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1030 __ Cmp(rdx, Smi::FromInt(0));
1031 __ j(equal, &update_each, Label::kNear);
1032
1005 // Convert the entry to a string or null if it isn't a property 1033 // Convert the entry to a string or null if it isn't a property
1006 // anymore. If the property has been removed while iterating, we 1034 // anymore. If the property has been removed while iterating, we
1007 // just skip it. 1035 // just skip it.
1008 __ push(rcx); // Enumerable. 1036 __ push(rcx); // Enumerable.
1009 __ push(rbx); // Current entry. 1037 __ push(rbx); // Current entry.
1010 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1038 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1011 __ Cmp(rax, Smi::FromInt(0)); 1039 __ Cmp(rax, Smi::FromInt(0));
1012 __ j(equal, loop_statement.continue_label()); 1040 __ j(equal, loop_statement.continue_label());
1013 __ movq(rbx, rax); 1041 __ movq(rbx, rax);
1014 1042
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 // space for nested functions that don't need literals cloning. If 1076 // space for nested functions that don't need literals cloning. If
1049 // we're running with the --always-opt or the --prepare-always-opt 1077 // we're running with the --always-opt or the --prepare-always-opt
1050 // flag, we need to use the runtime function so that the new function 1078 // flag, we need to use the runtime function so that the new function
1051 // we are creating here gets a chance to have its code optimized and 1079 // we are creating here gets a chance to have its code optimized and
1052 // doesn't just get a copy of the existing unoptimized code. 1080 // doesn't just get a copy of the existing unoptimized code.
1053 if (!FLAG_always_opt && 1081 if (!FLAG_always_opt &&
1054 !FLAG_prepare_always_opt && 1082 !FLAG_prepare_always_opt &&
1055 !pretenure && 1083 !pretenure &&
1056 scope()->is_function_scope() && 1084 scope()->is_function_scope() &&
1057 info->num_literals() == 0) { 1085 info->num_literals() == 0) {
1058 FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode); 1086 FastNewClosureStub stub(info->strict_mode_flag());
1059 __ Push(info); 1087 __ Push(info);
1060 __ CallStub(&stub); 1088 __ CallStub(&stub);
1061 } else { 1089 } else {
1062 __ push(rsi); 1090 __ push(rsi);
1063 __ Push(info); 1091 __ Push(info);
1064 __ Push(pretenure 1092 __ Push(pretenure
1065 ? isolate()->factory()->true_value() 1093 ? isolate()->factory()->true_value()
1066 : isolate()->factory()->false_value()); 1094 : isolate()->factory()->false_value());
1067 __ CallRuntime(Runtime::kNewClosure, 3); 1095 __ CallRuntime(Runtime::kNewClosure, 3);
1068 } 1096 }
1069 context()->Plug(rax); 1097 context()->Plug(rax);
1070 } 1098 }
1071 1099
1072 1100
1073 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 1101 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1074 Comment cmnt(masm_, "[ VariableProxy"); 1102 Comment cmnt(masm_, "[ VariableProxy");
1075 EmitVariableLoad(expr); 1103 EmitVariableLoad(expr);
1076 } 1104 }
1077 1105
1078 1106
1079 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, 1107 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1080 TypeofState typeof_state, 1108 TypeofState typeof_state,
1081 Label* slow) { 1109 Label* slow) {
1082 Register context = rsi; 1110 Register context = rsi;
1083 Register temp = rdx; 1111 Register temp = rdx;
1084 1112
1085 Scope* s = scope(); 1113 Scope* s = scope();
1086 while (s != NULL) { 1114 while (s != NULL) {
1087 if (s->num_heap_slots() > 0) { 1115 if (s->num_heap_slots() > 0) {
1088 if (s->calls_eval()) { 1116 if (s->calls_non_strict_eval()) {
1089 // Check that extension is NULL. 1117 // Check that extension is NULL.
1090 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1118 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1091 Immediate(0)); 1119 Immediate(0));
1092 __ j(not_equal, slow); 1120 __ j(not_equal, slow);
1093 } 1121 }
1094 // Load next context in chain. 1122 // Load next context in chain.
1095 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1123 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1096 // Walk the rest of the chain without clobbering rsi. 1124 // Walk the rest of the chain without clobbering rsi.
1097 context = temp; 1125 context = temp;
1098 } 1126 }
1099 // If no outer scope calls eval, we do not need to check more 1127 // If no outer scope calls eval, we do not need to check more
1100 // context extensions. If we have reached an eval scope, we check 1128 // context extensions. If we have reached an eval scope, we check
1101 // all extensions from this point. 1129 // all extensions from this point.
1102 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 1130 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
1103 s = s->outer_scope(); 1131 s = s->outer_scope();
1104 } 1132 }
1105 1133
1106 if (s != NULL && s->is_eval_scope()) { 1134 if (s != NULL && s->is_eval_scope()) {
1107 // Loop up the context chain. There is no frame effect so it is 1135 // Loop up the context chain. There is no frame effect so it is
1108 // safe to use raw labels here. 1136 // safe to use raw labels here.
1109 Label next, fast; 1137 Label next, fast;
1110 if (!context.is(temp)) { 1138 if (!context.is(temp)) {
1111 __ movq(temp, context); 1139 __ movq(temp, context);
1112 } 1140 }
(...skipping 25 matching lines...) Expand all
1138 1166
1139 1167
1140 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1168 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1141 Label* slow) { 1169 Label* slow) {
1142 ASSERT(var->IsContextSlot()); 1170 ASSERT(var->IsContextSlot());
1143 Register context = rsi; 1171 Register context = rsi;
1144 Register temp = rbx; 1172 Register temp = rbx;
1145 1173
1146 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1174 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1147 if (s->num_heap_slots() > 0) { 1175 if (s->num_heap_slots() > 0) {
1148 if (s->calls_eval()) { 1176 if (s->calls_non_strict_eval()) {
1149 // Check that extension is NULL. 1177 // Check that extension is NULL.
1150 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1178 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1151 Immediate(0)); 1179 Immediate(0));
1152 __ j(not_equal, slow); 1180 __ j(not_equal, slow);
1153 } 1181 }
1154 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1182 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1155 // Walk the rest of the chain without clobbering rsi. 1183 // Walk the rest of the chain without clobbering rsi.
1156 context = temp; 1184 context = temp;
1157 } 1185 }
1158 } 1186 }
(...skipping 16 matching lines...) Expand all
1175 // eval-introduced variables. Eval is used a lot without 1203 // eval-introduced variables. Eval is used a lot without
1176 // introducing variables. In those cases, we do not want to 1204 // introducing variables. In those cases, we do not want to
1177 // perform a runtime call for all variables in the scope 1205 // perform a runtime call for all variables in the scope
1178 // containing the eval. 1206 // containing the eval.
1179 if (var->mode() == DYNAMIC_GLOBAL) { 1207 if (var->mode() == DYNAMIC_GLOBAL) {
1180 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1208 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1181 __ jmp(done); 1209 __ jmp(done);
1182 } else if (var->mode() == DYNAMIC_LOCAL) { 1210 } else if (var->mode() == DYNAMIC_LOCAL) {
1183 Variable* local = var->local_if_not_shadowed(); 1211 Variable* local = var->local_if_not_shadowed();
1184 __ movq(rax, ContextSlotOperandCheckExtensions(local, slow)); 1212 __ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
1185 if (local->mode() == CONST || local->mode() == LET) { 1213 if (local->mode() == CONST ||
1214 local->mode() == CONST_HARMONY ||
1215 local->mode() == LET) {
1186 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1216 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1187 __ j(not_equal, done); 1217 __ j(not_equal, done);
1188 if (local->mode() == CONST) { 1218 if (local->mode() == CONST) {
1189 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1219 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1190 } else { // LET 1220 } else { // LET || CONST_HARMONY
1191 __ Push(var->name()); 1221 __ Push(var->name());
1192 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1222 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1193 } 1223 }
1194 } 1224 }
1195 __ jmp(done); 1225 __ jmp(done);
1196 } 1226 }
1197 } 1227 }
1198 1228
1199 1229
1200 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1230 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
(...skipping 13 matching lines...) Expand all
1214 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1244 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1215 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1245 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1216 context()->Plug(rax); 1246 context()->Plug(rax);
1217 break; 1247 break;
1218 } 1248 }
1219 1249
1220 case Variable::PARAMETER: 1250 case Variable::PARAMETER:
1221 case Variable::LOCAL: 1251 case Variable::LOCAL:
1222 case Variable::CONTEXT: { 1252 case Variable::CONTEXT: {
1223 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); 1253 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
1224 if (var->mode() != LET && var->mode() != CONST) { 1254 if (!var->binding_needs_init()) {
1225 context()->Plug(var); 1255 context()->Plug(var);
1226 } else { 1256 } else {
1227 // Let and const need a read barrier. 1257 // Let and const need a read barrier.
1228 Label done; 1258 Label done;
1229 GetVar(rax, var); 1259 GetVar(rax, var);
1230 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1260 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1231 __ j(not_equal, &done, Label::kNear); 1261 __ j(not_equal, &done, Label::kNear);
1232 if (var->mode() == LET) { 1262 if (var->mode() == LET || var->mode() == CONST_HARMONY) {
1263 // Throw a reference error when using an uninitialized let/const
1264 // binding in harmony mode.
1233 __ Push(var->name()); 1265 __ Push(var->name());
1234 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1266 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1235 } else { // CONST 1267 } else {
1268 // Uninitalized const bindings outside of harmony mode are unholed.
1269 ASSERT(var->mode() == CONST);
1236 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1270 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1237 } 1271 }
1238 __ bind(&done); 1272 __ bind(&done);
1239 context()->Plug(rax); 1273 context()->Plug(rax);
1240 } 1274 }
1241 break; 1275 break;
1242 } 1276 }
1243 1277
1244 case Variable::LOOKUP: { 1278 case Variable::LOOKUP: {
1245 Label done, slow; 1279 Label done, slow;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1410 context()->Plug(rax); 1444 context()->Plug(rax);
1411 } 1445 }
1412 } 1446 }
1413 1447
1414 1448
1415 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1449 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1416 Comment cmnt(masm_, "[ ArrayLiteral"); 1450 Comment cmnt(masm_, "[ ArrayLiteral");
1417 1451
1418 ZoneList<Expression*>* subexprs = expr->values(); 1452 ZoneList<Expression*>* subexprs = expr->values();
1419 int length = subexprs->length(); 1453 int length = subexprs->length();
1454 Handle<FixedArray> constant_elements = expr->constant_elements();
1455 ASSERT_EQ(2, constant_elements->length());
1456 ElementsKind constant_elements_kind =
1457 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1458 Handle<FixedArrayBase> constant_elements_values(
1459 FixedArrayBase::cast(constant_elements->get(1)));
1420 1460
1421 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1461 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1422 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1462 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1423 __ Push(Smi::FromInt(expr->literal_index())); 1463 __ Push(Smi::FromInt(expr->literal_index()));
1424 __ Push(expr->constant_elements()); 1464 __ Push(constant_elements);
1425 if (expr->constant_elements()->map() == 1465 if (constant_elements_values->map() ==
1426 isolate()->heap()->fixed_cow_array_map()) { 1466 isolate()->heap()->fixed_cow_array_map()) {
1427 FastCloneShallowArrayStub stub( 1467 FastCloneShallowArrayStub stub(
1428 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 1468 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1429 __ CallStub(&stub); 1469 __ CallStub(&stub);
1430 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); 1470 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1431 } else if (expr->depth() > 1) { 1471 } else if (expr->depth() > 1) {
1432 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1472 __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1433 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1473 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1434 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1474 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1435 } else { 1475 } else {
1436 FastCloneShallowArrayStub stub( 1476 ASSERT(constant_elements_kind == FAST_ELEMENTS ||
1437 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); 1477 constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
1478 FLAG_smi_only_arrays);
1479 FastCloneShallowArrayStub::Mode mode =
1480 constant_elements_kind == FAST_DOUBLE_ELEMENTS
1481 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
1482 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
1483 FastCloneShallowArrayStub stub(mode, length);
1438 __ CallStub(&stub); 1484 __ CallStub(&stub);
1439 } 1485 }
1440 1486
1441 bool result_saved = false; // Is the result saved to the stack? 1487 bool result_saved = false; // Is the result saved to the stack?
1442 1488
1443 // Emit code to evaluate all the non-constant subexpressions and to store 1489 // Emit code to evaluate all the non-constant subexpressions and to store
1444 // them into the newly cloned array. 1490 // them into the newly cloned array.
1445 for (int i = 0; i < length; i++) { 1491 for (int i = 0; i < length; i++) {
1446 Expression* subexpr = subexprs->at(i); 1492 Expression* subexpr = subexprs->at(i);
1447 // If the subexpression is a literal or a simple materialized literal it 1493 // If the subexpression is a literal or a simple materialized literal it
1448 // is already set in the cloned array. 1494 // is already set in the cloned array.
1449 if (subexpr->AsLiteral() != NULL || 1495 if (subexpr->AsLiteral() != NULL ||
1450 CompileTimeValue::IsCompileTimeValue(subexpr)) { 1496 CompileTimeValue::IsCompileTimeValue(subexpr)) {
1451 continue; 1497 continue;
1452 } 1498 }
1453 1499
1454 if (!result_saved) { 1500 if (!result_saved) {
1455 __ push(rax); 1501 __ push(rax);
1456 result_saved = true; 1502 result_saved = true;
1457 } 1503 }
1458 VisitForAccumulatorValue(subexpr); 1504 VisitForAccumulatorValue(subexpr);
1459 1505
1460 // Store the subexpression value in the array's elements. 1506 // Store the subexpression value in the array's elements.
1461 __ movq(r8, Operand(rsp, 0)); // Copy of array literal. 1507 __ movq(r8, Operand(rsp, 0)); // Copy of array literal.
1508 __ movq(rdi, FieldOperand(r8, JSObject::kMapOffset));
1462 __ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset)); 1509 __ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset));
1463 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1510 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1511
1512 Label element_done;
1513 Label double_elements;
1514 Label smi_element;
1515 Label slow_elements;
1516 Label fast_elements;
1517 __ CheckFastElements(rdi, &double_elements);
1518
1519 // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
1520 __ JumpIfSmi(result_register(), &smi_element);
1521 __ CheckFastSmiOnlyElements(rdi, &fast_elements);
1522
1523 // Store into the array literal requires a elements transition. Call into
1524 // the runtime.
1525 __ bind(&slow_elements);
1526 __ push(r8); // Copy of array literal.
1527 __ Push(Smi::FromInt(i));
1528 __ push(result_register());
1529 __ Push(Smi::FromInt(NONE)); // PropertyAttributes
1530 __ Push(Smi::FromInt(strict_mode_flag())); // Strict mode.
1531 __ CallRuntime(Runtime::kSetProperty, 5);
1532 __ jmp(&element_done);
1533
1534 // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
1535 __ bind(&double_elements);
1536 __ movq(rcx, Immediate(i));
1537 __ StoreNumberToDoubleElements(result_register(),
1538 rbx,
1539 rcx,
1540 xmm0,
1541 &slow_elements);
1542 __ jmp(&element_done);
1543
1544 // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
1545 __ bind(&fast_elements);
1464 __ movq(FieldOperand(rbx, offset), result_register()); 1546 __ movq(FieldOperand(rbx, offset), result_register());
1465
1466 Label no_map_change;
1467 __ JumpIfSmi(result_register(), &no_map_change);
1468 // Update the write barrier for the array store. 1547 // Update the write barrier for the array store.
1469 __ RecordWriteField(rbx, offset, result_register(), rcx, 1548 __ RecordWriteField(rbx, offset, result_register(), rcx,
1470 kDontSaveFPRegs, 1549 kDontSaveFPRegs,
1471 EMIT_REMEMBERED_SET, 1550 EMIT_REMEMBERED_SET,
1472 OMIT_SMI_CHECK); 1551 OMIT_SMI_CHECK);
1473 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); 1552 __ jmp(&element_done);
1474 __ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear); 1553
1475 __ push(r8); 1554 // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
1476 __ CallRuntime(Runtime::kNonSmiElementStored, 1); 1555 // FAST_ELEMENTS, and value is Smi.
1477 __ bind(&no_map_change); 1556 __ bind(&smi_element);
1557 __ movq(FieldOperand(rbx, offset), result_register());
1558 // Fall through
1559
1560 __ bind(&element_done);
1478 1561
1479 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1562 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1480 } 1563 }
1481 1564
1482 if (result_saved) { 1565 if (result_saved) {
1483 context()->PlugTOS(); 1566 context()->PlugTOS();
1484 } else { 1567 } else {
1485 context()->Plug(rax); 1568 context()->Plug(rax);
1486 } 1569 }
1487 } 1570 }
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1798 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1881 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1799 __ bind(&assign); 1882 __ bind(&assign);
1800 __ movq(location, rax); 1883 __ movq(location, rax);
1801 if (var->IsContextSlot()) { 1884 if (var->IsContextSlot()) {
1802 __ movq(rdx, rax); 1885 __ movq(rdx, rax);
1803 __ RecordWriteContextSlot( 1886 __ RecordWriteContextSlot(
1804 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 1887 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
1805 } 1888 }
1806 } 1889 }
1807 1890
1808 } else if (var->mode() != CONST) { 1891 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
1809 // Assignment to var or initializing assignment to let. 1892 // Assignment to var or initializing assignment to let/const
1893 // in harmony mode.
1810 if (var->IsStackAllocated() || var->IsContextSlot()) { 1894 if (var->IsStackAllocated() || var->IsContextSlot()) {
1811 MemOperand location = VarOperand(var, rcx); 1895 MemOperand location = VarOperand(var, rcx);
1812 if (FLAG_debug_code && op == Token::INIT_LET) { 1896 if (FLAG_debug_code && op == Token::INIT_LET) {
1813 // Check for an uninitialized let binding. 1897 // Check for an uninitialized let binding.
1814 __ movq(rdx, location); 1898 __ movq(rdx, location);
1815 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1899 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1816 __ Check(equal, "Let binding re-initialization."); 1900 __ Check(equal, "Let binding re-initialization.");
1817 } 1901 }
1818 // Perform the assignment. 1902 // Perform the assignment.
1819 __ movq(location, rax); 1903 __ movq(location, rax);
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
2650 // Allocate a heap number. 2734 // Allocate a heap number.
2651 __ CallRuntime(Runtime::kNumberAlloc, 0); 2735 __ CallRuntime(Runtime::kNumberAlloc, 0);
2652 __ movq(rbx, rax); 2736 __ movq(rbx, rax);
2653 2737
2654 __ bind(&heapnumber_allocated); 2738 __ bind(&heapnumber_allocated);
2655 2739
2656 // Return a random uint32 number in rax. 2740 // Return a random uint32 number in rax.
2657 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. 2741 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
2658 __ PrepareCallCFunction(1); 2742 __ PrepareCallCFunction(1);
2659 #ifdef _WIN64 2743 #ifdef _WIN64
2660 __ LoadAddress(rcx, ExternalReference::isolate_address()); 2744 __ movq(rcx, ContextOperand(context_register(), Context::GLOBAL_INDEX));
2745 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
2746
2661 #else 2747 #else
2662 __ LoadAddress(rdi, ExternalReference::isolate_address()); 2748 __ movq(rdi, ContextOperand(context_register(), Context::GLOBAL_INDEX));
2749 __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2663 #endif 2750 #endif
2664 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 2751 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
2665 2752
2666 // Convert 32 random bits in rax to 0.(32 random bits) in a double 2753 // Convert 32 random bits in rax to 0.(32 random bits) in a double
2667 // by computing: 2754 // by computing:
2668 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2755 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2669 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2756 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2670 __ movd(xmm1, rcx); 2757 __ movd(xmm1, rcx);
2671 __ movd(xmm0, rax); 2758 __ movd(xmm0, rax);
2672 __ cvtss2sd(xmm1, xmm1); 2759 __ cvtss2sd(xmm1, xmm1);
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after
3990 break; 4077 break;
3991 } 4078 }
3992 4079
3993 default: { 4080 default: {
3994 VisitForAccumulatorValue(expr->right()); 4081 VisitForAccumulatorValue(expr->right());
3995 Condition cc = no_condition; 4082 Condition cc = no_condition;
3996 switch (op) { 4083 switch (op) {
3997 case Token::EQ_STRICT: 4084 case Token::EQ_STRICT:
3998 case Token::EQ: 4085 case Token::EQ:
3999 cc = equal; 4086 cc = equal;
4000 __ pop(rdx);
4001 break; 4087 break;
4002 case Token::LT: 4088 case Token::LT:
4003 cc = less; 4089 cc = less;
4004 __ pop(rdx);
4005 break; 4090 break;
4006 case Token::GT: 4091 case Token::GT:
4007 // Reverse left and right sizes to obtain ECMA-262 conversion order. 4092 cc = greater;
4008 cc = less;
4009 __ movq(rdx, result_register());
4010 __ pop(rax);
4011 break; 4093 break;
4012 case Token::LTE: 4094 case Token::LTE:
4013 // Reverse left and right sizes to obtain ECMA-262 conversion order. 4095 cc = less_equal;
4014 cc = greater_equal;
4015 __ movq(rdx, result_register());
4016 __ pop(rax);
4017 break; 4096 break;
4018 case Token::GTE: 4097 case Token::GTE:
4019 cc = greater_equal; 4098 cc = greater_equal;
4020 __ pop(rdx);
4021 break; 4099 break;
4022 case Token::IN: 4100 case Token::IN:
4023 case Token::INSTANCEOF: 4101 case Token::INSTANCEOF:
4024 default: 4102 default:
4025 UNREACHABLE(); 4103 UNREACHABLE();
4026 } 4104 }
4105 __ pop(rdx);
4027 4106
4028 bool inline_smi_code = ShouldInlineSmiCase(op); 4107 bool inline_smi_code = ShouldInlineSmiCase(op);
4029 JumpPatchSite patch_site(masm_); 4108 JumpPatchSite patch_site(masm_);
4030 if (inline_smi_code) { 4109 if (inline_smi_code) {
4031 Label slow_case; 4110 Label slow_case;
4032 __ movq(rcx, rdx); 4111 __ movq(rcx, rdx);
4033 __ or_(rcx, rax); 4112 __ or_(rcx, rax);
4034 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4113 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4035 __ cmpq(rdx, rax); 4114 __ cmpq(rdx, rax);
4036 Split(cc, if_true, if_false, NULL); 4115 Split(cc, if_true, if_false, NULL);
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
4195 *context_length = 0; 4274 *context_length = 0;
4196 return previous_; 4275 return previous_;
4197 } 4276 }
4198 4277
4199 4278
4200 #undef __ 4279 #undef __
4201 4280
4202 } } // namespace v8::internal 4281 } } // namespace v8::internal
4203 4282
4204 #endif // V8_TARGET_ARCH_X64 4283 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/deoptimizer-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698