OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 } | 125 } |
126 | 126 |
127 | 127 |
128 TypeInfoCodeGenState::~TypeInfoCodeGenState() { | 128 TypeInfoCodeGenState::~TypeInfoCodeGenState() { |
129 owner()->set_type_info(slot_, old_type_info_); | 129 owner()->set_type_info(slot_, old_type_info_); |
130 } | 130 } |
131 | 131 |
132 // ------------------------------------------------------------------------- | 132 // ------------------------------------------------------------------------- |
133 // CodeGenerator implementation | 133 // CodeGenerator implementation |
134 | 134 |
135 int CodeGenerator::inlined_write_barrier_size_ = -1; | |
136 | |
137 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 135 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
138 : deferred_(8), | 136 : deferred_(8), |
139 masm_(masm), | 137 masm_(masm), |
140 info_(NULL), | 138 info_(NULL), |
141 frame_(NULL), | 139 frame_(NULL), |
142 allocator_(NULL), | 140 allocator_(NULL), |
143 cc_reg_(al), | 141 cc_reg_(al), |
144 state_(NULL), | 142 state_(NULL), |
145 loop_nesting_(0), | 143 loop_nesting_(0), |
146 type_info_(NULL), | 144 type_info_(NULL), |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 frame_->CallRuntime(Runtime::kTraceEnter, 0); | 298 frame_->CallRuntime(Runtime::kTraceEnter, 0); |
301 // Ignore the return value. | 299 // Ignore the return value. |
302 } | 300 } |
303 | 301 |
304 // Compile the body of the function in a vanilla state. Don't | 302 // Compile the body of the function in a vanilla state. Don't |
305 // bother compiling all the code if the scope has an illegal | 303 // bother compiling all the code if the scope has an illegal |
306 // redeclaration. | 304 // redeclaration. |
307 if (!scope()->HasIllegalRedeclaration()) { | 305 if (!scope()->HasIllegalRedeclaration()) { |
308 Comment cmnt(masm_, "[ function body"); | 306 Comment cmnt(masm_, "[ function body"); |
309 #ifdef DEBUG | 307 #ifdef DEBUG |
310 bool is_builtin = Bootstrapper::IsActive(); | 308 bool is_builtin = Isolate::Current()->bootstrapper()->IsActive(); |
311 bool should_trace = | 309 bool should_trace = |
312 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 310 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
313 if (should_trace) { | 311 if (should_trace) { |
314 frame_->CallRuntime(Runtime::kDebugTrace, 0); | 312 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
315 // Ignore the return value. | 313 // Ignore the return value. |
316 } | 314 } |
317 #endif | 315 #endif |
318 VisitStatements(info->function()->body()); | 316 VisitStatements(info->function()->body()); |
319 } | 317 } |
320 } | 318 } |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 | 763 |
766 // Check if the value is a smi. | 764 // Check if the value is a smi. |
767 __ cmp(tos, Operand(Smi::FromInt(0))); | 765 __ cmp(tos, Operand(Smi::FromInt(0))); |
768 | 766 |
769 if (!known_smi) { | 767 if (!known_smi) { |
770 false_target->Branch(eq); | 768 false_target->Branch(eq); |
771 __ tst(tos, Operand(kSmiTagMask)); | 769 __ tst(tos, Operand(kSmiTagMask)); |
772 true_target->Branch(eq); | 770 true_target->Branch(eq); |
773 | 771 |
774 // Slow case. | 772 // Slow case. |
775 if (CpuFeatures::IsSupported(VFP3)) { | 773 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
776 CpuFeatures::Scope scope(VFP3); | 774 CpuFeatures::Scope scope(VFP3); |
777 // Implements the slow case by using ToBooleanStub. | 775 // Implements the slow case by using ToBooleanStub. |
778 // The ToBooleanStub takes a single argument, and | 776 // The ToBooleanStub takes a single argument, and |
779 // returns a non-zero value for true, or zero for false. | 777 // returns a non-zero value for true, or zero for false. |
780 // Both the argument value and the return value use the | 778 // Both the argument value and the return value use the |
781 // register assigned to tos_ | 779 // register assigned to tos_ |
782 ToBooleanStub stub(tos); | 780 ToBooleanStub stub(tos); |
783 frame_->CallStub(&stub, 0); | 781 frame_->CallStub(&stub, 0); |
784 // Convert the result in "tos" to a condition code. | 782 // Convert the result in "tos" to a condition code. |
785 __ cmp(tos, Operand(0, RelocInfo::NONE)); | 783 __ cmp(tos, Operand(0, RelocInfo::NONE)); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 | 960 |
963 __ b(cond, &non_smi_input_); | 961 __ b(cond, &non_smi_input_); |
964 } | 962 } |
965 | 963 |
966 | 964 |
967 // For bit operations the result is always 32bits so we handle the case where | 965 // For bit operations the result is always 32bits so we handle the case where |
968 // the result does not fit in a Smi without calling the generic stub. | 966 // the result does not fit in a Smi without calling the generic stub. |
969 void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond) { | 967 void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond) { |
970 ASSERT(Token::IsBitOp(op_)); | 968 ASSERT(Token::IsBitOp(op_)); |
971 | 969 |
972 if ((op_ == Token::SHR) && !CpuFeatures::IsSupported(VFP3)) { | 970 if ((op_ == Token::SHR) && |
| 971 !Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
973 // >>> requires an unsigned to double conversion and the non VFP code | 972 // >>> requires an unsigned to double conversion and the non VFP code |
974 // does not support this conversion. | 973 // does not support this conversion. |
975 __ b(cond, entry_label()); | 974 __ b(cond, entry_label()); |
976 } else { | 975 } else { |
977 __ b(cond, &answer_out_of_range_); | 976 __ b(cond, &answer_out_of_range_); |
978 } | 977 } |
979 } | 978 } |
980 | 979 |
981 | 980 |
982 // On entry the non-constant side of the binary operation is in tos_register_ | 981 // On entry the non-constant side of the binary operation is in tos_register_ |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 if (answer_out_of_range_.is_linked()) { | 1065 if (answer_out_of_range_.is_linked()) { |
1067 GenerateAnswerOutOfRange(); | 1066 GenerateAnswerOutOfRange(); |
1068 } | 1067 } |
1069 } | 1068 } |
1070 | 1069 |
1071 | 1070 |
1072 // Convert and write the integer answer into heap_number. | 1071 // Convert and write the integer answer into heap_number. |
1073 void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer, | 1072 void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer, |
1074 Register heap_number, | 1073 Register heap_number, |
1075 Register scratch) { | 1074 Register scratch) { |
1076 if (CpuFeatures::IsSupported(VFP3)) { | 1075 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
1077 CpuFeatures::Scope scope(VFP3); | 1076 CpuFeatures::Scope scope(VFP3); |
1078 __ vmov(s0, answer); | 1077 __ vmov(s0, answer); |
1079 if (op_ == Token::SHR) { | 1078 if (op_ == Token::SHR) { |
1080 __ vcvt_f64_u32(d0, s0); | 1079 __ vcvt_f64_u32(d0, s0); |
1081 } else { | 1080 } else { |
1082 __ vcvt_f64_s32(d0, s0); | 1081 __ vcvt_f64_s32(d0, s0); |
1083 } | 1082 } |
1084 __ sub(scratch, heap_number, Operand(kHeapObjectTag)); | 1083 __ sub(scratch, heap_number, Operand(kHeapObjectTag)); |
1085 __ vstr(d0, scratch, HeapNumber::kValueOffset); | 1084 __ vstr(d0, scratch, HeapNumber::kValueOffset); |
1086 } else { | 1085 } else { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 } | 1135 } |
1137 break; | 1136 break; |
1138 case Token::SHR: | 1137 case Token::SHR: |
1139 ASSERT(!reversed_); | 1138 ASSERT(!reversed_); |
1140 if (shift_value != 0) { | 1139 if (shift_value != 0) { |
1141 __ mov(int32, Operand(int32, LSR, shift_value), SetCC); | 1140 __ mov(int32, Operand(int32, LSR, shift_value), SetCC); |
1142 } else { | 1141 } else { |
1143 // SHR is special because it is required to produce a positive answer. | 1142 // SHR is special because it is required to produce a positive answer. |
1144 __ cmp(int32, Operand(0, RelocInfo::NONE)); | 1143 __ cmp(int32, Operand(0, RelocInfo::NONE)); |
1145 } | 1144 } |
1146 if (CpuFeatures::IsSupported(VFP3)) { | 1145 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
1147 __ b(mi, &result_not_a_smi); | 1146 __ b(mi, &result_not_a_smi); |
1148 } else { | 1147 } else { |
1149 // Non VFP code cannot convert from unsigned to double, so fall back | 1148 // Non VFP code cannot convert from unsigned to double, so fall back |
1150 // to GenericBinaryOpStub. | 1149 // to GenericBinaryOpStub. |
1151 __ b(mi, entry_label()); | 1150 __ b(mi, entry_label()); |
1152 } | 1151 } |
1153 break; | 1152 break; |
1154 case Token::SHL: | 1153 case Token::SHL: |
1155 ASSERT(!reversed_); | 1154 ASSERT(!reversed_); |
1156 if (shift_value != 0) { | 1155 if (shift_value != 0) { |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1717 // stack, as receiver and arguments, and calls x. | 1716 // stack, as receiver and arguments, and calls x. |
1718 // In the implementation comments, we call x the applicand | 1717 // In the implementation comments, we call x the applicand |
1719 // and y the receiver. | 1718 // and y the receiver. |
1720 | 1719 |
1721 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); | 1720 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); |
1722 ASSERT(arguments->IsArguments()); | 1721 ASSERT(arguments->IsArguments()); |
1723 | 1722 |
1724 // Load applicand.apply onto the stack. This will usually | 1723 // Load applicand.apply onto the stack. This will usually |
1725 // give us a megamorphic load site. Not super, but it works. | 1724 // give us a megamorphic load site. Not super, but it works. |
1726 Load(applicand); | 1725 Load(applicand); |
1727 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 1726 Handle<String> name = FACTORY->LookupAsciiSymbol("apply"); |
1728 frame_->Dup(); | 1727 frame_->Dup(); |
1729 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); | 1728 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); |
1730 frame_->EmitPush(r0); | 1729 frame_->EmitPush(r0); |
1731 | 1730 |
1732 // Load the receiver and the existing arguments object onto the | 1731 // Load the receiver and the existing arguments object onto the |
1733 // expression stack. Avoid allocating the arguments object here. | 1732 // expression stack. Avoid allocating the arguments object here. |
1734 Load(receiver); | 1733 Load(receiver); |
1735 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); | 1734 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); |
1736 | 1735 |
1737 // At this point the top two stack elements are probably in registers | 1736 // At this point the top two stack elements are probably in registers |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1779 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
1781 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 1780 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); |
1782 __ CompareObjectType(receiver_reg, r2, r3, FIRST_JS_OBJECT_TYPE); | 1781 __ CompareObjectType(receiver_reg, r2, r3, FIRST_JS_OBJECT_TYPE); |
1783 __ b(lt, &build_args); | 1782 __ b(lt, &build_args); |
1784 | 1783 |
1785 // Check that applicand.apply is Function.prototype.apply. | 1784 // Check that applicand.apply is Function.prototype.apply. |
1786 __ ldr(r0, MemOperand(sp, kPointerSize)); | 1785 __ ldr(r0, MemOperand(sp, kPointerSize)); |
1787 __ JumpIfSmi(r0, &build_args); | 1786 __ JumpIfSmi(r0, &build_args); |
1788 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); | 1787 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); |
1789 __ b(ne, &build_args); | 1788 __ b(ne, &build_args); |
1790 Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply)); | 1789 Handle<Code> apply_code( |
| 1790 Isolate::Current()->builtins()->builtin(Builtins::FunctionApply)); |
1791 __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); | 1791 __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); |
1792 __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1792 __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1793 __ cmp(r1, Operand(apply_code)); | 1793 __ cmp(r1, Operand(apply_code)); |
1794 __ b(ne, &build_args); | 1794 __ b(ne, &build_args); |
1795 | 1795 |
1796 // Check that applicand is a function. | 1796 // Check that applicand is a function. |
1797 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | 1797 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
1798 __ JumpIfSmi(r1, &build_args); | 1798 __ JumpIfSmi(r1, &build_args); |
1799 __ CompareObjectType(r1, r2, r3, JS_FUNCTION_TYPE); | 1799 __ CompareObjectType(r1, r2, r3, JS_FUNCTION_TYPE); |
1800 __ b(ne, &build_args); | 1800 __ b(ne, &build_args); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1995 | 1995 |
1996 ASSERT(frame_->height() == original_height); | 1996 ASSERT(frame_->height() == original_height); |
1997 return; | 1997 return; |
1998 } | 1998 } |
1999 | 1999 |
2000 ASSERT(!var->is_global()); | 2000 ASSERT(!var->is_global()); |
2001 | 2001 |
2002 // If we have a function or a constant, we need to initialize the variable. | 2002 // If we have a function or a constant, we need to initialize the variable. |
2003 Expression* val = NULL; | 2003 Expression* val = NULL; |
2004 if (node->mode() == Variable::CONST) { | 2004 if (node->mode() == Variable::CONST) { |
2005 val = new Literal(Factory::the_hole_value()); | 2005 val = new Literal(FACTORY->the_hole_value()); |
2006 } else { | 2006 } else { |
2007 val = node->fun(); // NULL if we don't have a function | 2007 val = node->fun(); // NULL if we don't have a function |
2008 } | 2008 } |
2009 | 2009 |
2010 | 2010 |
2011 if (val != NULL) { | 2011 if (val != NULL) { |
2012 WriteBarrierCharacter wb_info = | 2012 WriteBarrierCharacter wb_info = |
2013 val->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI; | 2013 val->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI; |
2014 if (val->AsLiteral() != NULL) wb_info = NEVER_NEWSPACE; | 2014 if (val->AsLiteral() != NULL) wb_info = NEVER_NEWSPACE; |
2015 // Set initial value. | 2015 // Set initial value. |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2852 // After shadowing stops, the original labels are unshadowed and the | 2852 // After shadowing stops, the original labels are unshadowed and the |
2853 // LabelShadows represent the formerly shadowing labels. | 2853 // LabelShadows represent the formerly shadowing labels. |
2854 bool has_unlinks = false; | 2854 bool has_unlinks = false; |
2855 for (int i = 0; i < shadows.length(); i++) { | 2855 for (int i = 0; i < shadows.length(); i++) { |
2856 shadows[i]->StopShadowing(); | 2856 shadows[i]->StopShadowing(); |
2857 has_unlinks = has_unlinks || shadows[i]->is_linked(); | 2857 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
2858 } | 2858 } |
2859 function_return_is_shadowed_ = function_return_was_shadowed; | 2859 function_return_is_shadowed_ = function_return_was_shadowed; |
2860 | 2860 |
2861 // Get an external reference to the handler address. | 2861 // Get an external reference to the handler address. |
2862 ExternalReference handler_address(Top::k_handler_address); | 2862 ExternalReference handler_address(Isolate::k_handler_address); |
2863 | 2863 |
2864 // If we can fall off the end of the try block, unlink from try chain. | 2864 // If we can fall off the end of the try block, unlink from try chain. |
2865 if (has_valid_frame()) { | 2865 if (has_valid_frame()) { |
2866 // The next handler address is on top of the frame. Unlink from | 2866 // The next handler address is on top of the frame. Unlink from |
2867 // the handler list and drop the rest of this handler from the | 2867 // the handler list and drop the rest of this handler from the |
2868 // frame. | 2868 // frame. |
2869 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2869 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2870 frame_->EmitPop(r1); // r0 can contain the return value. | 2870 frame_->EmitPop(r1); // r0 can contain the return value. |
2871 __ mov(r3, Operand(handler_address)); | 2871 __ mov(r3, Operand(handler_address)); |
2872 __ str(r1, MemOperand(r3)); | 2872 __ str(r1, MemOperand(r3)); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2968 // After shadowing stops, the original labels are unshadowed and the | 2968 // After shadowing stops, the original labels are unshadowed and the |
2969 // LabelShadows represent the formerly shadowing labels. | 2969 // LabelShadows represent the formerly shadowing labels. |
2970 int nof_unlinks = 0; | 2970 int nof_unlinks = 0; |
2971 for (int i = 0; i < shadows.length(); i++) { | 2971 for (int i = 0; i < shadows.length(); i++) { |
2972 shadows[i]->StopShadowing(); | 2972 shadows[i]->StopShadowing(); |
2973 if (shadows[i]->is_linked()) nof_unlinks++; | 2973 if (shadows[i]->is_linked()) nof_unlinks++; |
2974 } | 2974 } |
2975 function_return_is_shadowed_ = function_return_was_shadowed; | 2975 function_return_is_shadowed_ = function_return_was_shadowed; |
2976 | 2976 |
2977 // Get an external reference to the handler address. | 2977 // Get an external reference to the handler address. |
2978 ExternalReference handler_address(Top::k_handler_address); | 2978 ExternalReference handler_address(Isolate::k_handler_address); |
2979 | 2979 |
2980 // If we can fall off the end of the try block, unlink from the try | 2980 // If we can fall off the end of the try block, unlink from the try |
2981 // chain and set the state on the frame to FALLING. | 2981 // chain and set the state on the frame to FALLING. |
2982 if (has_valid_frame()) { | 2982 if (has_valid_frame()) { |
2983 // The next handler address is on top of the frame. | 2983 // The next handler address is on top of the frame. |
2984 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2984 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2985 frame_->EmitPop(r1); | 2985 frame_->EmitPop(r1); |
2986 __ mov(r3, Operand(handler_address)); | 2986 __ mov(r3, Operand(handler_address)); |
2987 __ str(r1, MemOperand(r3)); | 2987 __ str(r1, MemOperand(r3)); |
2988 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2988 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3123 function_info->strict_mode() ? kStrictMode : kNonStrictMode); | 3123 function_info->strict_mode() ? kStrictMode : kNonStrictMode); |
3124 frame_->EmitPush(Operand(function_info)); | 3124 frame_->EmitPush(Operand(function_info)); |
3125 frame_->SpillAll(); | 3125 frame_->SpillAll(); |
3126 frame_->CallStub(&stub, 1); | 3126 frame_->CallStub(&stub, 1); |
3127 frame_->EmitPush(r0); | 3127 frame_->EmitPush(r0); |
3128 } else { | 3128 } else { |
3129 // Create a new closure. | 3129 // Create a new closure. |
3130 frame_->EmitPush(cp); | 3130 frame_->EmitPush(cp); |
3131 frame_->EmitPush(Operand(function_info)); | 3131 frame_->EmitPush(Operand(function_info)); |
3132 frame_->EmitPush(Operand(pretenure | 3132 frame_->EmitPush(Operand(pretenure |
3133 ? Factory::true_value() | 3133 ? FACTORY->true_value() |
3134 : Factory::false_value())); | 3134 : FACTORY->false_value())); |
3135 frame_->CallRuntime(Runtime::kNewClosure, 3); | 3135 frame_->CallRuntime(Runtime::kNewClosure, 3); |
3136 frame_->EmitPush(r0); | 3136 frame_->EmitPush(r0); |
3137 } | 3137 } |
3138 } | 3138 } |
3139 | 3139 |
3140 | 3140 |
3141 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 3141 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
3142 #ifdef DEBUG | 3142 #ifdef DEBUG |
3143 int original_height = frame_->height(); | 3143 int original_height = frame_->height(); |
3144 #endif | 3144 #endif |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3624 Literal* key = property->key(); | 3624 Literal* key = property->key(); |
3625 Expression* value = property->value(); | 3625 Expression* value = property->value(); |
3626 switch (property->kind()) { | 3626 switch (property->kind()) { |
3627 case ObjectLiteral::Property::CONSTANT: | 3627 case ObjectLiteral::Property::CONSTANT: |
3628 break; | 3628 break; |
3629 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 3629 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
3630 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 3630 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
3631 // else fall through | 3631 // else fall through |
3632 case ObjectLiteral::Property::COMPUTED: | 3632 case ObjectLiteral::Property::COMPUTED: |
3633 if (key->handle()->IsSymbol()) { | 3633 if (key->handle()->IsSymbol()) { |
3634 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3634 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 3635 Builtins::StoreIC_Initialize)); |
3635 Load(value); | 3636 Load(value); |
3636 if (property->emit_store()) { | 3637 if (property->emit_store()) { |
3637 frame_->PopToR0(); | 3638 frame_->PopToR0(); |
3638 // Fetch the object literal. | 3639 // Fetch the object literal. |
3639 frame_->SpillAllButCopyTOSToR1(); | 3640 frame_->SpillAllButCopyTOSToR1(); |
3640 __ mov(r2, Operand(key->handle())); | 3641 __ mov(r2, Operand(key->handle())); |
3641 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 3642 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
3642 } else { | 3643 } else { |
3643 frame_->Drop(); | 3644 frame_->Drop(); |
3644 } | 3645 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3687 | 3688 |
3688 Register tos = frame_->GetTOSRegister(); | 3689 Register tos = frame_->GetTOSRegister(); |
3689 // Load the function of this activation. | 3690 // Load the function of this activation. |
3690 __ ldr(tos, frame_->Function()); | 3691 __ ldr(tos, frame_->Function()); |
3691 // Load the literals array of the function. | 3692 // Load the literals array of the function. |
3692 __ ldr(tos, FieldMemOperand(tos, JSFunction::kLiteralsOffset)); | 3693 __ ldr(tos, FieldMemOperand(tos, JSFunction::kLiteralsOffset)); |
3693 frame_->EmitPush(tos); | 3694 frame_->EmitPush(tos); |
3694 frame_->EmitPush(Operand(Smi::FromInt(node->literal_index()))); | 3695 frame_->EmitPush(Operand(Smi::FromInt(node->literal_index()))); |
3695 frame_->EmitPush(Operand(node->constant_elements())); | 3696 frame_->EmitPush(Operand(node->constant_elements())); |
3696 int length = node->values()->length(); | 3697 int length = node->values()->length(); |
3697 if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) { | 3698 if (node->constant_elements()->map() == HEAP->fixed_cow_array_map()) { |
3698 FastCloneShallowArrayStub stub( | 3699 FastCloneShallowArrayStub stub( |
3699 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); | 3700 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); |
3700 frame_->CallStub(&stub, 3); | 3701 frame_->CallStub(&stub, 3); |
3701 __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2); | 3702 __ IncrementCounter(COUNTERS->cow_arrays_created_stub(), 1, r1, r2); |
3702 } else if (node->depth() > 1) { | 3703 } else if (node->depth() > 1) { |
3703 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); | 3704 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); |
3704 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 3705 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
3705 frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 3706 frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
3706 } else { | 3707 } else { |
3707 FastCloneShallowArrayStub stub( | 3708 FastCloneShallowArrayStub stub( |
3708 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); | 3709 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); |
3709 frame_->CallStub(&stub, 3); | 3710 frame_->CallStub(&stub, 3); |
3710 } | 3711 } |
3711 frame_->EmitPush(r0); // save the result | 3712 frame_->EmitPush(r0); // save the result |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4247 // Load the arguments. | 4248 // Load the arguments. |
4248 int arg_count = args->length(); | 4249 int arg_count = args->length(); |
4249 for (int i = 0; i < arg_count; i++) { | 4250 for (int i = 0; i < arg_count; i++) { |
4250 Load(args->at(i)); | 4251 Load(args->at(i)); |
4251 } | 4252 } |
4252 | 4253 |
4253 VirtualFrame::SpilledScope spilled_scope(frame_); | 4254 VirtualFrame::SpilledScope spilled_scope(frame_); |
4254 // Setup the name register and call the IC initialization code. | 4255 // Setup the name register and call the IC initialization code. |
4255 __ mov(r2, Operand(var->name())); | 4256 __ mov(r2, Operand(var->name())); |
4256 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4257 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4257 Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop); | 4258 Handle<Code> stub = |
| 4259 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
4258 CodeForSourcePosition(node->position()); | 4260 CodeForSourcePosition(node->position()); |
4259 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 4261 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
4260 arg_count + 1); | 4262 arg_count + 1); |
4261 __ ldr(cp, frame_->Context()); | 4263 __ ldr(cp, frame_->Context()); |
4262 frame_->EmitPush(r0); | 4264 frame_->EmitPush(r0); |
4263 | 4265 |
4264 } else if (var != NULL && var->AsSlot() != NULL && | 4266 } else if (var != NULL && var->AsSlot() != NULL && |
4265 var->AsSlot()->type() == Slot::LOOKUP) { | 4267 var->AsSlot()->type() == Slot::LOOKUP) { |
4266 // ---------------------------------- | 4268 // ---------------------------------- |
4267 // JavaScript examples: | 4269 // JavaScript examples: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4342 int arg_count = args->length(); | 4344 int arg_count = args->length(); |
4343 for (int i = 0; i < arg_count; i++) { | 4345 for (int i = 0; i < arg_count; i++) { |
4344 Load(args->at(i)); | 4346 Load(args->at(i)); |
4345 } | 4347 } |
4346 | 4348 |
4347 VirtualFrame::SpilledScope spilled_scope(frame_); | 4349 VirtualFrame::SpilledScope spilled_scope(frame_); |
4348 // Set the name register and call the IC initialization code. | 4350 // Set the name register and call the IC initialization code. |
4349 __ mov(r2, Operand(name)); | 4351 __ mov(r2, Operand(name)); |
4350 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4352 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4351 Handle<Code> stub = | 4353 Handle<Code> stub = |
4352 StubCache::ComputeCallInitialize(arg_count, in_loop); | 4354 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
4353 CodeForSourcePosition(node->position()); | 4355 CodeForSourcePosition(node->position()); |
4354 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 4356 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
4355 __ ldr(cp, frame_->Context()); | 4357 __ ldr(cp, frame_->Context()); |
4356 frame_->EmitPush(r0); | 4358 frame_->EmitPush(r0); |
4357 } | 4359 } |
4358 | 4360 |
4359 } else { | 4361 } else { |
4360 // ------------------------------------------- | 4362 // ------------------------------------------- |
4361 // JavaScript example: 'array[index](1, 2, 3)' | 4363 // JavaScript example: 'array[index](1, 2, 3)' |
4362 // ------------------------------------------- | 4364 // ------------------------------------------- |
(...skipping 21 matching lines...) Expand all Loading... |
4384 | 4386 |
4385 // Load the arguments. | 4387 // Load the arguments. |
4386 int arg_count = args->length(); | 4388 int arg_count = args->length(); |
4387 for (int i = 0; i < arg_count; i++) { | 4389 for (int i = 0; i < arg_count; i++) { |
4388 Load(args->at(i)); | 4390 Load(args->at(i)); |
4389 } | 4391 } |
4390 | 4392 |
4391 // Load the key into r2 and call the IC initialization code. | 4393 // Load the key into r2 and call the IC initialization code. |
4392 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4394 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4393 Handle<Code> stub = | 4395 Handle<Code> stub = |
4394 StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 4396 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, |
| 4397 in_loop); |
4395 CodeForSourcePosition(node->position()); | 4398 CodeForSourcePosition(node->position()); |
4396 frame_->SpillAll(); | 4399 frame_->SpillAll(); |
4397 __ ldr(r2, frame_->ElementAt(arg_count + 1)); | 4400 __ ldr(r2, frame_->ElementAt(arg_count + 1)); |
4398 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 4401 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
4399 frame_->Drop(); // Drop the key still on the stack. | 4402 frame_->Drop(); // Drop the key still on the stack. |
4400 __ ldr(cp, frame_->Context()); | 4403 __ ldr(cp, frame_->Context()); |
4401 frame_->EmitPush(r0); | 4404 frame_->EmitPush(r0); |
4402 } | 4405 } |
4403 } | 4406 } |
4404 | 4407 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4449 VirtualFrame::SpilledScope spilled_scope(frame_); | 4452 VirtualFrame::SpilledScope spilled_scope(frame_); |
4450 | 4453 |
4451 // Load the argument count into r0 and the function into r1 as per | 4454 // Load the argument count into r0 and the function into r1 as per |
4452 // calling convention. | 4455 // calling convention. |
4453 __ mov(r0, Operand(arg_count)); | 4456 __ mov(r0, Operand(arg_count)); |
4454 __ ldr(r1, frame_->ElementAt(arg_count)); | 4457 __ ldr(r1, frame_->ElementAt(arg_count)); |
4455 | 4458 |
4456 // Call the construct call builtin that handles allocation and | 4459 // Call the construct call builtin that handles allocation and |
4457 // constructor invocation. | 4460 // constructor invocation. |
4458 CodeForSourcePosition(node->position()); | 4461 CodeForSourcePosition(node->position()); |
4459 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 4462 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 4463 Builtins::JSConstructCall)); |
4460 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); | 4464 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); |
4461 frame_->EmitPush(r0); | 4465 frame_->EmitPush(r0); |
4462 | 4466 |
4463 ASSERT_EQ(original_height + 1, frame_->height()); | 4467 ASSERT_EQ(original_height + 1, frame_->height()); |
4464 } | 4468 } |
4465 | 4469 |
4466 | 4470 |
4467 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 4471 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
4468 Register scratch = VirtualFrame::scratch0(); | 4472 Register scratch = VirtualFrame::scratch0(); |
4469 JumpTarget null, function, leave, non_function_constructor; | 4473 JumpTarget null, function, leave, non_function_constructor; |
(...skipping 28 matching lines...) Expand all Loading... |
4498 // The tos register now contains the constructor function. Grab the | 4502 // The tos register now contains the constructor function. Grab the |
4499 // instance class name from there. | 4503 // instance class name from there. |
4500 __ ldr(tos, FieldMemOperand(tos, JSFunction::kSharedFunctionInfoOffset)); | 4504 __ ldr(tos, FieldMemOperand(tos, JSFunction::kSharedFunctionInfoOffset)); |
4501 __ ldr(tos, | 4505 __ ldr(tos, |
4502 FieldMemOperand(tos, SharedFunctionInfo::kInstanceClassNameOffset)); | 4506 FieldMemOperand(tos, SharedFunctionInfo::kInstanceClassNameOffset)); |
4503 frame_->EmitPush(tos); | 4507 frame_->EmitPush(tos); |
4504 leave.Jump(); | 4508 leave.Jump(); |
4505 | 4509 |
4506 // Functions have class 'Function'. | 4510 // Functions have class 'Function'. |
4507 function.Bind(); | 4511 function.Bind(); |
4508 __ mov(tos, Operand(Factory::function_class_symbol())); | 4512 __ mov(tos, Operand(FACTORY->function_class_symbol())); |
4509 frame_->EmitPush(tos); | 4513 frame_->EmitPush(tos); |
4510 leave.Jump(); | 4514 leave.Jump(); |
4511 | 4515 |
4512 // Objects with a non-function constructor have class 'Object'. | 4516 // Objects with a non-function constructor have class 'Object'. |
4513 non_function_constructor.Bind(); | 4517 non_function_constructor.Bind(); |
4514 __ mov(tos, Operand(Factory::Object_symbol())); | 4518 __ mov(tos, Operand(FACTORY->Object_symbol())); |
4515 frame_->EmitPush(tos); | 4519 frame_->EmitPush(tos); |
4516 leave.Jump(); | 4520 leave.Jump(); |
4517 | 4521 |
4518 // Non-JS objects have class null. | 4522 // Non-JS objects have class null. |
4519 null.Bind(); | 4523 null.Bind(); |
4520 __ LoadRoot(tos, Heap::kNullValueRootIndex); | 4524 __ LoadRoot(tos, Heap::kNullValueRootIndex); |
4521 frame_->EmitPush(tos); | 4525 frame_->EmitPush(tos); |
4522 | 4526 |
4523 // All done. | 4527 // All done. |
4524 leave.Bind(); | 4528 leave.Bind(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4605 cc_reg_ = eq; | 4609 cc_reg_ = eq; |
4606 } | 4610 } |
4607 | 4611 |
4608 | 4612 |
4609 // Generates the Math.pow method. | 4613 // Generates the Math.pow method. |
4610 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | 4614 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
4611 ASSERT(args->length() == 2); | 4615 ASSERT(args->length() == 2); |
4612 Load(args->at(0)); | 4616 Load(args->at(0)); |
4613 Load(args->at(1)); | 4617 Load(args->at(1)); |
4614 | 4618 |
4615 if (!CpuFeatures::IsSupported(VFP3)) { | 4619 if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
4616 frame_->CallRuntime(Runtime::kMath_pow, 2); | 4620 frame_->CallRuntime(Runtime::kMath_pow, 2); |
4617 frame_->EmitPush(r0); | 4621 frame_->EmitPush(r0); |
4618 } else { | 4622 } else { |
4619 CpuFeatures::Scope scope(VFP3); | 4623 CpuFeatures::Scope scope(VFP3); |
4620 JumpTarget runtime, done; | 4624 JumpTarget runtime, done; |
4621 Label exponent_nonsmi, base_nonsmi, powi, not_minus_half, allocate_return; | 4625 Label exponent_nonsmi, base_nonsmi, powi, not_minus_half, allocate_return; |
4622 | 4626 |
4623 Register scratch1 = VirtualFrame::scratch0(); | 4627 Register scratch1 = VirtualFrame::scratch0(); |
4624 Register scratch2 = VirtualFrame::scratch1(); | 4628 Register scratch2 = VirtualFrame::scratch1(); |
4625 | 4629 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4759 frame_->EmitPush(base); | 4763 frame_->EmitPush(base); |
4760 } | 4764 } |
4761 } | 4765 } |
4762 | 4766 |
4763 | 4767 |
4764 // Generates the Math.sqrt method. | 4768 // Generates the Math.sqrt method. |
4765 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | 4769 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
4766 ASSERT(args->length() == 1); | 4770 ASSERT(args->length() == 1); |
4767 Load(args->at(0)); | 4771 Load(args->at(0)); |
4768 | 4772 |
4769 if (!CpuFeatures::IsSupported(VFP3)) { | 4773 if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
4770 frame_->CallRuntime(Runtime::kMath_sqrt, 1); | 4774 frame_->CallRuntime(Runtime::kMath_sqrt, 1); |
4771 frame_->EmitPush(r0); | 4775 frame_->EmitPush(r0); |
4772 } else { | 4776 } else { |
4773 CpuFeatures::Scope scope(VFP3); | 4777 CpuFeatures::Scope scope(VFP3); |
4774 JumpTarget runtime, done; | 4778 JumpTarget runtime, done; |
4775 | 4779 |
4776 Register scratch1 = VirtualFrame::scratch0(); | 4780 Register scratch1 = VirtualFrame::scratch0(); |
4777 Register scratch2 = VirtualFrame::scratch1(); | 4781 Register scratch2 = VirtualFrame::scratch1(); |
4778 | 4782 |
4779 // Get the value from the frame. | 4783 // Get the value from the frame. |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5145 // Calculate location of the first key name. | 5149 // Calculate location of the first key name. |
5146 __ add(map_result_, | 5150 __ add(map_result_, |
5147 map_result_, | 5151 map_result_, |
5148 Operand(FixedArray::kHeaderSize - kHeapObjectTag + | 5152 Operand(FixedArray::kHeaderSize - kHeapObjectTag + |
5149 DescriptorArray::kFirstIndex * kPointerSize)); | 5153 DescriptorArray::kFirstIndex * kPointerSize)); |
5150 // Loop through all the keys in the descriptor array. If one of these is the | 5154 // Loop through all the keys in the descriptor array. If one of these is the |
5151 // symbol valueOf the result is false. | 5155 // symbol valueOf the result is false. |
5152 Label entry, loop; | 5156 Label entry, loop; |
5153 // The use of ip to store the valueOf symbol asumes that it is not otherwise | 5157 // The use of ip to store the valueOf symbol asumes that it is not otherwise |
5154 // used in the loop below. | 5158 // used in the loop below. |
5155 __ mov(ip, Operand(Factory::value_of_symbol())); | 5159 __ mov(ip, Operand(FACTORY->value_of_symbol())); |
5156 __ jmp(&entry); | 5160 __ jmp(&entry); |
5157 __ bind(&loop); | 5161 __ bind(&loop); |
5158 __ ldr(scratch2_, MemOperand(map_result_, 0)); | 5162 __ ldr(scratch2_, MemOperand(map_result_, 0)); |
5159 __ cmp(scratch2_, ip); | 5163 __ cmp(scratch2_, ip); |
5160 __ b(eq, &false_result); | 5164 __ b(eq, &false_result); |
5161 __ add(map_result_, map_result_, Operand(kPointerSize)); | 5165 __ add(map_result_, map_result_, Operand(kPointerSize)); |
5162 __ bind(&entry); | 5166 __ bind(&entry); |
5163 __ cmp(map_result_, Operand(scratch1_)); | 5167 __ cmp(map_result_, Operand(scratch1_)); |
5164 __ b(ne, &loop); | 5168 __ b(ne, &loop); |
5165 | 5169 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5348 __ bind(&slow_allocate_heapnumber); | 5352 __ bind(&slow_allocate_heapnumber); |
5349 // Allocate a heap number. | 5353 // Allocate a heap number. |
5350 __ CallRuntime(Runtime::kNumberAlloc, 0); | 5354 __ CallRuntime(Runtime::kNumberAlloc, 0); |
5351 __ mov(r4, Operand(r0)); | 5355 __ mov(r4, Operand(r0)); |
5352 | 5356 |
5353 __ bind(&heapnumber_allocated); | 5357 __ bind(&heapnumber_allocated); |
5354 | 5358 |
5355 // Convert 32 random bits in r0 to 0.(32 random bits) in a double | 5359 // Convert 32 random bits in r0 to 0.(32 random bits) in a double |
5356 // by computing: | 5360 // by computing: |
5357 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 5361 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
5358 if (CpuFeatures::IsSupported(VFP3)) { | 5362 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
5359 __ PrepareCallCFunction(0, r1); | 5363 __ PrepareCallCFunction(0, r1); |
5360 __ CallCFunction(ExternalReference::random_uint32_function(), 0); | 5364 __ CallCFunction(ExternalReference::random_uint32_function(), 0); |
5361 | 5365 |
5362 CpuFeatures::Scope scope(VFP3); | 5366 CpuFeatures::Scope scope(VFP3); |
5363 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | 5367 // 0x41300000 is the top half of 1.0 x 2^20 as a double. |
5364 // Create this constant using mov/orr to avoid PC relative load. | 5368 // Create this constant using mov/orr to avoid PC relative load. |
5365 __ mov(r1, Operand(0x41000000)); | 5369 __ mov(r1, Operand(0x41000000)); |
5366 __ orr(r1, r1, Operand(0x300000)); | 5370 __ orr(r1, r1, Operand(0x300000)); |
5367 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. | 5371 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. |
5368 __ vmov(d7, r0, r1); | 5372 __ vmov(d7, r0, r1); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5472 } | 5476 } |
5473 | 5477 |
5474 | 5478 |
5475 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { | 5479 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { |
5476 ASSERT_EQ(2, args->length()); | 5480 ASSERT_EQ(2, args->length()); |
5477 | 5481 |
5478 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 5482 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
5479 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 5483 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
5480 | 5484 |
5481 Handle<FixedArray> jsfunction_result_caches( | 5485 Handle<FixedArray> jsfunction_result_caches( |
5482 Top::global_context()->jsfunction_result_caches()); | 5486 Isolate::Current()->global_context()->jsfunction_result_caches()); |
5483 if (jsfunction_result_caches->length() <= cache_id) { | 5487 if (jsfunction_result_caches->length() <= cache_id) { |
5484 __ Abort("Attempt to use undefined cache."); | 5488 __ Abort("Attempt to use undefined cache."); |
5485 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); | 5489 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
5486 return; | 5490 return; |
5487 } | 5491 } |
5488 | 5492 |
5489 Load(args->at(1)); | 5493 Load(args->at(1)); |
5490 | 5494 |
5491 frame_->PopToR1(); | 5495 frame_->PopToR1(); |
5492 frame_->SpillAll(); | 5496 frame_->SpillAll(); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5662 } | 5666 } |
5663 Load(args->at(n_args + 1)); // function | 5667 Load(args->at(n_args + 1)); // function |
5664 frame_->CallJSFunction(n_args); | 5668 frame_->CallJSFunction(n_args); |
5665 frame_->EmitPush(r0); | 5669 frame_->EmitPush(r0); |
5666 } | 5670 } |
5667 | 5671 |
5668 | 5672 |
5669 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 5673 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
5670 ASSERT_EQ(args->length(), 1); | 5674 ASSERT_EQ(args->length(), 1); |
5671 Load(args->at(0)); | 5675 Load(args->at(0)); |
5672 if (CpuFeatures::IsSupported(VFP3)) { | 5676 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
5673 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 5677 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
5674 TranscendentalCacheStub::TAGGED); | 5678 TranscendentalCacheStub::TAGGED); |
5675 frame_->SpillAllButCopyTOSToR0(); | 5679 frame_->SpillAllButCopyTOSToR0(); |
5676 frame_->CallStub(&stub, 1); | 5680 frame_->CallStub(&stub, 1); |
5677 } else { | 5681 } else { |
5678 frame_->CallRuntime(Runtime::kMath_sin, 1); | 5682 frame_->CallRuntime(Runtime::kMath_sin, 1); |
5679 } | 5683 } |
5680 frame_->EmitPush(r0); | 5684 frame_->EmitPush(r0); |
5681 } | 5685 } |
5682 | 5686 |
5683 | 5687 |
5684 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 5688 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
5685 ASSERT_EQ(args->length(), 1); | 5689 ASSERT_EQ(args->length(), 1); |
5686 Load(args->at(0)); | 5690 Load(args->at(0)); |
5687 if (CpuFeatures::IsSupported(VFP3)) { | 5691 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
5688 TranscendentalCacheStub stub(TranscendentalCache::COS, | 5692 TranscendentalCacheStub stub(TranscendentalCache::COS, |
5689 TranscendentalCacheStub::TAGGED); | 5693 TranscendentalCacheStub::TAGGED); |
5690 frame_->SpillAllButCopyTOSToR0(); | 5694 frame_->SpillAllButCopyTOSToR0(); |
5691 frame_->CallStub(&stub, 1); | 5695 frame_->CallStub(&stub, 1); |
5692 } else { | 5696 } else { |
5693 frame_->CallRuntime(Runtime::kMath_cos, 1); | 5697 frame_->CallRuntime(Runtime::kMath_cos, 1); |
5694 } | 5698 } |
5695 frame_->EmitPush(r0); | 5699 frame_->EmitPush(r0); |
5696 } | 5700 } |
5697 | 5701 |
5698 | 5702 |
5699 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { | 5703 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { |
5700 ASSERT_EQ(args->length(), 1); | 5704 ASSERT_EQ(args->length(), 1); |
5701 Load(args->at(0)); | 5705 Load(args->at(0)); |
5702 if (CpuFeatures::IsSupported(VFP3)) { | 5706 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
5703 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 5707 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
5704 TranscendentalCacheStub::TAGGED); | 5708 TranscendentalCacheStub::TAGGED); |
5705 frame_->SpillAllButCopyTOSToR0(); | 5709 frame_->SpillAllButCopyTOSToR0(); |
5706 frame_->CallStub(&stub, 1); | 5710 frame_->CallStub(&stub, 1); |
5707 } else { | 5711 } else { |
5708 frame_->CallRuntime(Runtime::kMath_log, 1); | 5712 frame_->CallRuntime(Runtime::kMath_log, 1); |
5709 } | 5713 } |
5710 frame_->EmitPush(r0); | 5714 frame_->EmitPush(r0); |
5711 } | 5715 } |
5712 | 5716 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5797 int original_height = frame_->height(); | 5801 int original_height = frame_->height(); |
5798 #endif | 5802 #endif |
5799 if (CheckForInlineRuntimeCall(node)) { | 5803 if (CheckForInlineRuntimeCall(node)) { |
5800 ASSERT((has_cc() && frame_->height() == original_height) || | 5804 ASSERT((has_cc() && frame_->height() == original_height) || |
5801 (!has_cc() && frame_->height() == original_height + 1)); | 5805 (!has_cc() && frame_->height() == original_height + 1)); |
5802 return; | 5806 return; |
5803 } | 5807 } |
5804 | 5808 |
5805 ZoneList<Expression*>* args = node->arguments(); | 5809 ZoneList<Expression*>* args = node->arguments(); |
5806 Comment cmnt(masm_, "[ CallRuntime"); | 5810 Comment cmnt(masm_, "[ CallRuntime"); |
5807 Runtime::Function* function = node->function(); | 5811 const Runtime::Function* function = node->function(); |
5808 | 5812 |
5809 if (function == NULL) { | 5813 if (function == NULL) { |
5810 // Prepare stack for calling JS runtime function. | 5814 // Prepare stack for calling JS runtime function. |
5811 // Push the builtins object found in the current global object. | 5815 // Push the builtins object found in the current global object. |
5812 Register scratch = VirtualFrame::scratch0(); | 5816 Register scratch = VirtualFrame::scratch0(); |
5813 __ ldr(scratch, GlobalObjectOperand()); | 5817 __ ldr(scratch, GlobalObjectOperand()); |
5814 Register builtins = frame_->GetTOSRegister(); | 5818 Register builtins = frame_->GetTOSRegister(); |
5815 __ ldr(builtins, FieldMemOperand(scratch, GlobalObject::kBuiltinsOffset)); | 5819 __ ldr(builtins, FieldMemOperand(scratch, GlobalObject::kBuiltinsOffset)); |
5816 frame_->EmitPush(builtins); | 5820 frame_->EmitPush(builtins); |
5817 } | 5821 } |
5818 | 5822 |
5819 // Push the arguments ("left-to-right"). | 5823 // Push the arguments ("left-to-right"). |
5820 int arg_count = args->length(); | 5824 int arg_count = args->length(); |
5821 for (int i = 0; i < arg_count; i++) { | 5825 for (int i = 0; i < arg_count; i++) { |
5822 Load(args->at(i)); | 5826 Load(args->at(i)); |
5823 } | 5827 } |
5824 | 5828 |
5825 VirtualFrame::SpilledScope spilled_scope(frame_); | 5829 VirtualFrame::SpilledScope spilled_scope(frame_); |
5826 | 5830 |
5827 if (function == NULL) { | 5831 if (function == NULL) { |
5828 // Call the JS runtime function. | 5832 // Call the JS runtime function. |
5829 __ mov(r2, Operand(node->name())); | 5833 __ mov(r2, Operand(node->name())); |
5830 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 5834 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
5831 Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop); | 5835 Handle<Code> stub = |
| 5836 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
5832 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 5837 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
5833 __ ldr(cp, frame_->Context()); | 5838 __ ldr(cp, frame_->Context()); |
5834 frame_->EmitPush(r0); | 5839 frame_->EmitPush(r0); |
5835 } else { | 5840 } else { |
5836 // Call the C runtime function. | 5841 // Call the C runtime function. |
5837 frame_->CallRuntime(function, arg_count); | 5842 frame_->CallRuntime(function, arg_count); |
5838 frame_->EmitPush(r0); | 5843 frame_->EmitPush(r0); |
5839 } | 5844 } |
5840 ASSERT_EQ(original_height + 1, frame_->height()); | 5845 ASSERT_EQ(original_height + 1, frame_->height()); |
5841 } | 5846 } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6356 (right->AsLiteral() != NULL && | 6361 (right->AsLiteral() != NULL && |
6357 right->AsLiteral()->handle()->IsString())) { | 6362 right->AsLiteral()->handle()->IsString())) { |
6358 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 6363 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
6359 | 6364 |
6360 // Load the operand, move it to a register. | 6365 // Load the operand, move it to a register. |
6361 LoadTypeofExpression(operation->expression()); | 6366 LoadTypeofExpression(operation->expression()); |
6362 Register tos = frame_->PopToRegister(); | 6367 Register tos = frame_->PopToRegister(); |
6363 | 6368 |
6364 Register scratch = VirtualFrame::scratch0(); | 6369 Register scratch = VirtualFrame::scratch0(); |
6365 | 6370 |
6366 if (check->Equals(Heap::number_symbol())) { | 6371 if (check->Equals(HEAP->number_symbol())) { |
6367 __ tst(tos, Operand(kSmiTagMask)); | 6372 __ tst(tos, Operand(kSmiTagMask)); |
6368 true_target()->Branch(eq); | 6373 true_target()->Branch(eq); |
6369 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); | 6374 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); |
6370 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 6375 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
6371 __ cmp(tos, ip); | 6376 __ cmp(tos, ip); |
6372 cc_reg_ = eq; | 6377 cc_reg_ = eq; |
6373 | 6378 |
6374 } else if (check->Equals(Heap::string_symbol())) { | 6379 } else if (check->Equals(HEAP->string_symbol())) { |
6375 __ tst(tos, Operand(kSmiTagMask)); | 6380 __ tst(tos, Operand(kSmiTagMask)); |
6376 false_target()->Branch(eq); | 6381 false_target()->Branch(eq); |
6377 | 6382 |
6378 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); | 6383 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); |
6379 | 6384 |
6380 // It can be an undetectable string object. | 6385 // It can be an undetectable string object. |
6381 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset)); | 6386 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset)); |
6382 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable)); | 6387 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable)); |
6383 __ cmp(scratch, Operand(1 << Map::kIsUndetectable)); | 6388 __ cmp(scratch, Operand(1 << Map::kIsUndetectable)); |
6384 false_target()->Branch(eq); | 6389 false_target()->Branch(eq); |
6385 | 6390 |
6386 __ ldrb(scratch, FieldMemOperand(tos, Map::kInstanceTypeOffset)); | 6391 __ ldrb(scratch, FieldMemOperand(tos, Map::kInstanceTypeOffset)); |
6387 __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE)); | 6392 __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE)); |
6388 cc_reg_ = lt; | 6393 cc_reg_ = lt; |
6389 | 6394 |
6390 } else if (check->Equals(Heap::boolean_symbol())) { | 6395 } else if (check->Equals(HEAP->boolean_symbol())) { |
6391 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 6396 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
6392 __ cmp(tos, ip); | 6397 __ cmp(tos, ip); |
6393 true_target()->Branch(eq); | 6398 true_target()->Branch(eq); |
6394 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 6399 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
6395 __ cmp(tos, ip); | 6400 __ cmp(tos, ip); |
6396 cc_reg_ = eq; | 6401 cc_reg_ = eq; |
6397 | 6402 |
6398 } else if (check->Equals(Heap::undefined_symbol())) { | 6403 } else if (check->Equals(HEAP->undefined_symbol())) { |
6399 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 6404 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
6400 __ cmp(tos, ip); | 6405 __ cmp(tos, ip); |
6401 true_target()->Branch(eq); | 6406 true_target()->Branch(eq); |
6402 | 6407 |
6403 __ tst(tos, Operand(kSmiTagMask)); | 6408 __ tst(tos, Operand(kSmiTagMask)); |
6404 false_target()->Branch(eq); | 6409 false_target()->Branch(eq); |
6405 | 6410 |
6406 // It can be an undetectable object. | 6411 // It can be an undetectable object. |
6407 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); | 6412 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); |
6408 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset)); | 6413 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset)); |
6409 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable)); | 6414 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable)); |
6410 __ cmp(scratch, Operand(1 << Map::kIsUndetectable)); | 6415 __ cmp(scratch, Operand(1 << Map::kIsUndetectable)); |
6411 | 6416 |
6412 cc_reg_ = eq; | 6417 cc_reg_ = eq; |
6413 | 6418 |
6414 } else if (check->Equals(Heap::function_symbol())) { | 6419 } else if (check->Equals(HEAP->function_symbol())) { |
6415 __ tst(tos, Operand(kSmiTagMask)); | 6420 __ tst(tos, Operand(kSmiTagMask)); |
6416 false_target()->Branch(eq); | 6421 false_target()->Branch(eq); |
6417 Register map_reg = scratch; | 6422 Register map_reg = scratch; |
6418 __ CompareObjectType(tos, map_reg, tos, JS_FUNCTION_TYPE); | 6423 __ CompareObjectType(tos, map_reg, tos, JS_FUNCTION_TYPE); |
6419 true_target()->Branch(eq); | 6424 true_target()->Branch(eq); |
6420 // Regular expressions are callable so typeof == 'function'. | 6425 // Regular expressions are callable so typeof == 'function'. |
6421 __ CompareInstanceType(map_reg, tos, JS_REGEXP_TYPE); | 6426 __ CompareInstanceType(map_reg, tos, JS_REGEXP_TYPE); |
6422 cc_reg_ = eq; | 6427 cc_reg_ = eq; |
6423 | 6428 |
6424 } else if (check->Equals(Heap::object_symbol())) { | 6429 } else if (check->Equals(HEAP->object_symbol())) { |
6425 __ tst(tos, Operand(kSmiTagMask)); | 6430 __ tst(tos, Operand(kSmiTagMask)); |
6426 false_target()->Branch(eq); | 6431 false_target()->Branch(eq); |
6427 | 6432 |
6428 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 6433 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
6429 __ cmp(tos, ip); | 6434 __ cmp(tos, ip); |
6430 true_target()->Branch(eq); | 6435 true_target()->Branch(eq); |
6431 | 6436 |
6432 Register map_reg = scratch; | 6437 Register map_reg = scratch; |
6433 __ CompareObjectType(tos, map_reg, tos, JS_REGEXP_TYPE); | 6438 __ CompareObjectType(tos, map_reg, tos, JS_REGEXP_TYPE); |
6434 false_target()->Branch(eq); | 6439 false_target()->Branch(eq); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6576 void DeferredReferenceGetNamedValue::Generate() { | 6581 void DeferredReferenceGetNamedValue::Generate() { |
6577 #ifdef DEBUG | 6582 #ifdef DEBUG |
6578 int expected_height = frame_state()->frame()->height(); | 6583 int expected_height = frame_state()->frame()->height(); |
6579 #endif | 6584 #endif |
6580 VirtualFrame copied_frame(*frame_state()->frame()); | 6585 VirtualFrame copied_frame(*frame_state()->frame()); |
6581 copied_frame.SpillAll(); | 6586 copied_frame.SpillAll(); |
6582 | 6587 |
6583 Register scratch1 = VirtualFrame::scratch0(); | 6588 Register scratch1 = VirtualFrame::scratch0(); |
6584 Register scratch2 = VirtualFrame::scratch1(); | 6589 Register scratch2 = VirtualFrame::scratch1(); |
6585 ASSERT(!receiver_.is(scratch1) && !receiver_.is(scratch2)); | 6590 ASSERT(!receiver_.is(scratch1) && !receiver_.is(scratch2)); |
6586 __ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2); | 6591 __ DecrementCounter(COUNTERS->named_load_inline(), 1, scratch1, scratch2); |
6587 __ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1, scratch2); | 6592 __ IncrementCounter(COUNTERS->named_load_inline_miss(), 1, |
| 6593 scratch1, scratch2); |
6588 | 6594 |
6589 // Ensure receiver in r0 and name in r2 to match load ic calling convention. | 6595 // Ensure receiver in r0 and name in r2 to match load ic calling convention. |
6590 __ Move(r0, receiver_); | 6596 __ Move(r0, receiver_); |
6591 __ mov(r2, Operand(name_)); | 6597 __ mov(r2, Operand(name_)); |
6592 | 6598 |
6593 // The rest of the instructions in the deferred code must be together. | 6599 // The rest of the instructions in the deferred code must be together. |
6594 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6600 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6595 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 6601 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 6602 Builtins::LoadIC_Initialize)); |
6596 RelocInfo::Mode mode = is_contextual_ | 6603 RelocInfo::Mode mode = is_contextual_ |
6597 ? RelocInfo::CODE_TARGET_CONTEXT | 6604 ? RelocInfo::CODE_TARGET_CONTEXT |
6598 : RelocInfo::CODE_TARGET; | 6605 : RelocInfo::CODE_TARGET; |
6599 __ Call(ic, mode); | 6606 __ Call(ic, mode); |
6600 // We must mark the code just after the call with the correct marker. | 6607 // We must mark the code just after the call with the correct marker. |
6601 MacroAssembler::NopMarkerTypes code_marker; | 6608 MacroAssembler::NopMarkerTypes code_marker; |
6602 if (is_contextual_) { | 6609 if (is_contextual_) { |
6603 code_marker = is_dont_delete_ | 6610 code_marker = is_dont_delete_ |
6604 ? MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE | 6611 ? MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE |
6605 : MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT; | 6612 : MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6647 // in r0. | 6654 // in r0. |
6648 void DeferredReferenceGetKeyedValue::Generate() { | 6655 void DeferredReferenceGetKeyedValue::Generate() { |
6649 ASSERT((key_.is(r0) && receiver_.is(r1)) || | 6656 ASSERT((key_.is(r0) && receiver_.is(r1)) || |
6650 (key_.is(r1) && receiver_.is(r0))); | 6657 (key_.is(r1) && receiver_.is(r0))); |
6651 | 6658 |
6652 VirtualFrame copied_frame(*frame_state()->frame()); | 6659 VirtualFrame copied_frame(*frame_state()->frame()); |
6653 copied_frame.SpillAll(); | 6660 copied_frame.SpillAll(); |
6654 | 6661 |
6655 Register scratch1 = VirtualFrame::scratch0(); | 6662 Register scratch1 = VirtualFrame::scratch0(); |
6656 Register scratch2 = VirtualFrame::scratch1(); | 6663 Register scratch2 = VirtualFrame::scratch1(); |
6657 __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2); | 6664 __ DecrementCounter(COUNTERS->keyed_load_inline(), 1, scratch1, scratch2); |
6658 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2); | 6665 __ IncrementCounter(COUNTERS->keyed_load_inline_miss(), |
| 6666 1, scratch1, scratch2); |
6659 | 6667 |
6660 // Ensure key in r0 and receiver in r1 to match keyed load ic calling | 6668 // Ensure key in r0 and receiver in r1 to match keyed load ic calling |
6661 // convention. | 6669 // convention. |
6662 if (key_.is(r1)) { | 6670 if (key_.is(r1)) { |
6663 __ Swap(r0, r1, ip); | 6671 __ Swap(r0, r1, ip); |
6664 } | 6672 } |
6665 | 6673 |
6666 // The rest of the instructions in the deferred code must be together. | 6674 // The rest of the instructions in the deferred code must be together. |
6667 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6675 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6668 // Call keyed load IC. It has the arguments key and receiver in r0 and r1. | 6676 // Call keyed load IC. It has the arguments key and receiver in r0 and r1. |
6669 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 6677 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 6678 Builtins::KeyedLoadIC_Initialize)); |
6670 __ Call(ic, RelocInfo::CODE_TARGET); | 6679 __ Call(ic, RelocInfo::CODE_TARGET); |
6671 // The call must be followed by a nop instruction to indicate that the | 6680 // The call must be followed by a nop instruction to indicate that the |
6672 // keyed load has been inlined. | 6681 // keyed load has been inlined. |
6673 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6682 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
6674 | 6683 |
6675 // Now go back to the frame that we entered with. This will not overwrite | 6684 // Now go back to the frame that we entered with. This will not overwrite |
6676 // the receiver or key registers since they were not in use when we came | 6685 // the receiver or key registers since they were not in use when we came |
6677 // in. The instructions emitted by this merge are skipped over by the | 6686 // in. The instructions emitted by this merge are skipped over by the |
6678 // inline load patching mechanism when looking for the branch instruction | 6687 // inline load patching mechanism when looking for the branch instruction |
6679 // that tells it where the code to patch is. | 6688 // that tells it where the code to patch is. |
(...skipping 26 matching lines...) Expand all Loading... |
6706 Register value_; | 6715 Register value_; |
6707 Register key_; | 6716 Register key_; |
6708 Register receiver_; | 6717 Register receiver_; |
6709 StrictModeFlag strict_mode_; | 6718 StrictModeFlag strict_mode_; |
6710 }; | 6719 }; |
6711 | 6720 |
6712 | 6721 |
6713 void DeferredReferenceSetKeyedValue::Generate() { | 6722 void DeferredReferenceSetKeyedValue::Generate() { |
6714 Register scratch1 = VirtualFrame::scratch0(); | 6723 Register scratch1 = VirtualFrame::scratch0(); |
6715 Register scratch2 = VirtualFrame::scratch1(); | 6724 Register scratch2 = VirtualFrame::scratch1(); |
6716 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); | 6725 __ DecrementCounter(COUNTERS->keyed_store_inline(), 1, scratch1, scratch2); |
6717 __ IncrementCounter( | 6726 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), |
6718 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); | 6727 1, scratch1, scratch2); |
6719 | 6728 |
6720 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic | 6729 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic |
6721 // calling convention. | 6730 // calling convention. |
6722 if (value_.is(r1)) { | 6731 if (value_.is(r1)) { |
6723 __ Swap(r0, r1, ip); | 6732 __ Swap(r0, r1, ip); |
6724 } | 6733 } |
6725 ASSERT(receiver_.is(r2)); | 6734 ASSERT(receiver_.is(r2)); |
6726 | 6735 |
6727 // The rest of the instructions in the deferred code must be together. | 6736 // The rest of the instructions in the deferred code must be together. |
6728 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6737 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6729 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6738 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
6730 // r1 and r2. | 6739 // r1 and r2. |
6731 Handle<Code> ic(Builtins::builtin( | 6740 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
6732 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict | 6741 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict |
6733 : Builtins::KeyedStoreIC_Initialize)); | 6742 : Builtins::KeyedStoreIC_Initialize)); |
6734 __ Call(ic, RelocInfo::CODE_TARGET); | 6743 __ Call(ic, RelocInfo::CODE_TARGET); |
6735 // The call must be followed by a nop instruction to indicate that the | 6744 // The call must be followed by a nop instruction to indicate that the |
6736 // keyed store has been inlined. | 6745 // keyed store has been inlined. |
6737 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6746 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
6738 | 6747 |
6739 // Block the constant pool for one more instruction after leaving this | 6748 // Block the constant pool for one more instruction after leaving this |
6740 // constant pool block scope to include the branch instruction ending the | 6749 // constant pool block scope to include the branch instruction ending the |
6741 // deferred code. | 6750 // deferred code. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6776 | 6785 |
6777 // Ensure value in r0, receiver in r1 to match store ic calling | 6786 // Ensure value in r0, receiver in r1 to match store ic calling |
6778 // convention. | 6787 // convention. |
6779 ASSERT(value_.is(r0) && receiver_.is(r1)); | 6788 ASSERT(value_.is(r0) && receiver_.is(r1)); |
6780 __ mov(r2, Operand(name_)); | 6789 __ mov(r2, Operand(name_)); |
6781 | 6790 |
6782 // The rest of the instructions in the deferred code must be together. | 6791 // The rest of the instructions in the deferred code must be together. |
6783 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6792 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6784 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6793 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
6785 // r1 and r2. | 6794 // r1 and r2. |
6786 Handle<Code> ic(Builtins::builtin( | 6795 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
6787 (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict | 6796 (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict |
6788 : Builtins::StoreIC_Initialize)); | 6797 : Builtins::StoreIC_Initialize)); |
6789 __ Call(ic, RelocInfo::CODE_TARGET); | 6798 __ Call(ic, RelocInfo::CODE_TARGET); |
6790 // The call must be followed by a nop instruction to indicate that the | 6799 // The call must be followed by a nop instruction to indicate that the |
6791 // named store has been inlined. | 6800 // named store has been inlined. |
6792 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6801 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
6793 | 6802 |
6794 // Go back to the frame we entered with. The instructions | 6803 // Go back to the frame we entered with. The instructions |
6795 // generated by this merge are skipped over by the inline store | 6804 // generated by this merge are skipped over by the inline store |
6796 // patching mechanism when looking for the branch instruction that | 6805 // patching mechanism when looking for the branch instruction that |
6797 // tells it where the code to patch is. | 6806 // tells it where the code to patch is. |
6798 copied_frame.MergeTo(frame_state()->frame()); | 6807 copied_frame.MergeTo(frame_state()->frame()); |
6799 | 6808 |
6800 // Block the constant pool for one more instruction after leaving this | 6809 // Block the constant pool for one more instruction after leaving this |
6801 // constant pool block scope to include the branch instruction ending the | 6810 // constant pool block scope to include the branch instruction ending the |
6802 // deferred code. | 6811 // deferred code. |
6803 __ BlockConstPoolFor(1); | 6812 __ BlockConstPoolFor(1); |
6804 } | 6813 } |
6805 } | 6814 } |
6806 | 6815 |
6807 | 6816 |
6808 // Consumes the top of stack (the receiver) and pushes the result instead. | 6817 // Consumes the top of stack (the receiver) and pushes the result instead. |
6809 void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { | 6818 void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
6810 bool contextual_load_in_builtin = | 6819 bool contextual_load_in_builtin = |
6811 is_contextual && | 6820 is_contextual && |
6812 (Bootstrapper::IsActive() || | 6821 (ISOLATE->bootstrapper()->IsActive() || |
6813 (!info_->closure().is_null() && info_->closure()->IsBuiltin())); | 6822 (!info_->closure().is_null() && info_->closure()->IsBuiltin())); |
6814 | 6823 |
6815 if (scope()->is_global_scope() || | 6824 if (scope()->is_global_scope() || |
6816 loop_nesting() == 0 || | 6825 loop_nesting() == 0 || |
6817 contextual_load_in_builtin) { | 6826 contextual_load_in_builtin) { |
6818 Comment cmnt(masm(), "[ Load from named Property"); | 6827 Comment cmnt(masm(), "[ Load from named Property"); |
6819 // Setup the name register and call load IC. | 6828 // Setup the name register and call load IC. |
6820 frame_->CallLoadIC(name, | 6829 frame_->CallLoadIC(name, |
6821 is_contextual | 6830 is_contextual |
6822 ? RelocInfo::CODE_TARGET_CONTEXT | 6831 ? RelocInfo::CODE_TARGET_CONTEXT |
6823 : RelocInfo::CODE_TARGET); | 6832 : RelocInfo::CODE_TARGET); |
6824 frame_->EmitPush(r0); // Push answer. | 6833 frame_->EmitPush(r0); // Push answer. |
6825 } else { | 6834 } else { |
6826 // Inline the in-object property case. | 6835 // Inline the in-object property case. |
6827 Comment cmnt(masm(), is_contextual | 6836 Comment cmnt(masm(), is_contextual |
6828 ? "[ Inlined contextual property load" | 6837 ? "[ Inlined contextual property load" |
6829 : "[ Inlined named property load"); | 6838 : "[ Inlined named property load"); |
6830 | 6839 |
6831 // Counter will be decremented in the deferred code. Placed here to avoid | 6840 // Counter will be decremented in the deferred code. Placed here to avoid |
6832 // having it in the instruction stream below where patching will occur. | 6841 // having it in the instruction stream below where patching will occur. |
6833 if (is_contextual) { | 6842 if (is_contextual) { |
6834 __ IncrementCounter(&Counters::named_load_global_inline, 1, | 6843 __ IncrementCounter(COUNTERS->named_load_global_inline(), 1, |
6835 frame_->scratch0(), frame_->scratch1()); | 6844 frame_->scratch0(), frame_->scratch1()); |
6836 } else { | 6845 } else { |
6837 __ IncrementCounter(&Counters::named_load_inline, 1, | 6846 __ IncrementCounter(COUNTERS->named_load_inline(), 1, |
6838 frame_->scratch0(), frame_->scratch1()); | 6847 frame_->scratch0(), frame_->scratch1()); |
6839 } | 6848 } |
6840 | 6849 |
6841 // The following instructions are the inlined load of an in-object property. | 6850 // The following instructions are the inlined load of an in-object property. |
6842 // Parts of this code is patched, so the exact instructions generated needs | 6851 // Parts of this code is patched, so the exact instructions generated needs |
6843 // to be fixed. Therefore the instruction pool is blocked when generating | 6852 // to be fixed. Therefore the instruction pool is blocked when generating |
6844 // this code | 6853 // this code |
6845 | 6854 |
6846 // Load the receiver from the stack. | 6855 // Load the receiver from the stack. |
6847 Register receiver = frame_->PopToRegister(); | 6856 Register receiver = frame_->PopToRegister(); |
(...skipping 12 matching lines...) Expand all Loading... |
6860 LookupResult lookup; | 6869 LookupResult lookup; |
6861 global_object->LocalLookupRealNamedProperty(*name, &lookup); | 6870 global_object->LocalLookupRealNamedProperty(*name, &lookup); |
6862 if (lookup.IsProperty() && lookup.type() == NORMAL) { | 6871 if (lookup.IsProperty() && lookup.type() == NORMAL) { |
6863 ASSERT(lookup.holder() == global_object); | 6872 ASSERT(lookup.holder() == global_object); |
6864 ASSERT(global_object->property_dictionary()->ValueAt( | 6873 ASSERT(global_object->property_dictionary()->ValueAt( |
6865 lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell()); | 6874 lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell()); |
6866 is_dont_delete = lookup.IsDontDelete(); | 6875 is_dont_delete = lookup.IsDontDelete(); |
6867 } | 6876 } |
6868 } | 6877 } |
6869 if (is_dont_delete) { | 6878 if (is_dont_delete) { |
6870 __ IncrementCounter(&Counters::dont_delete_hint_hit, 1, | 6879 __ IncrementCounter(COUNTERS->dont_delete_hint_hit(), 1, |
6871 frame_->scratch0(), frame_->scratch1()); | 6880 frame_->scratch0(), frame_->scratch1()); |
6872 } | 6881 } |
6873 } | 6882 } |
6874 | 6883 |
6875 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6884 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6876 if (!is_contextual) { | 6885 if (!is_contextual) { |
6877 // Check that the receiver is a heap object. | 6886 // Check that the receiver is a heap object. |
6878 __ tst(receiver, Operand(kSmiTagMask)); | 6887 __ tst(receiver, Operand(kSmiTagMask)); |
6879 deferred->Branch(eq); | 6888 deferred->Branch(eq); |
6880 } | 6889 } |
(...skipping 16 matching lines...) Expand all Loading... |
6897 Label check_inlined_codesize; | 6906 Label check_inlined_codesize; |
6898 masm_->bind(&check_inlined_codesize); | 6907 masm_->bind(&check_inlined_codesize); |
6899 #endif | 6908 #endif |
6900 | 6909 |
6901 Register scratch = VirtualFrame::scratch0(); | 6910 Register scratch = VirtualFrame::scratch0(); |
6902 Register scratch2 = VirtualFrame::scratch1(); | 6911 Register scratch2 = VirtualFrame::scratch1(); |
6903 | 6912 |
6904 // Check the map. The null map used below is patched by the inline cache | 6913 // Check the map. The null map used below is patched by the inline cache |
6905 // code. Therefore we can't use a LoadRoot call. | 6914 // code. Therefore we can't use a LoadRoot call. |
6906 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 6915 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
6907 __ mov(scratch2, Operand(Factory::null_value())); | 6916 __ mov(scratch2, Operand(FACTORY->null_value())); |
6908 __ cmp(scratch, scratch2); | 6917 __ cmp(scratch, scratch2); |
6909 deferred->Branch(ne); | 6918 deferred->Branch(ne); |
6910 | 6919 |
6911 if (is_contextual) { | 6920 if (is_contextual) { |
6912 #ifdef DEBUG | 6921 #ifdef DEBUG |
6913 InlinedNamedLoadInstructions += 1; | 6922 InlinedNamedLoadInstructions += 1; |
6914 #endif | 6923 #endif |
6915 // Load the (initially invalid) cell and get its value. | 6924 // Load the (initially invalid) cell and get its value. |
6916 masm()->mov(receiver, Operand(Factory::null_value())); | 6925 masm()->mov(receiver, Operand(FACTORY->null_value())); |
6917 __ ldr(receiver, | 6926 __ ldr(receiver, |
6918 FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset)); | 6927 FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset)); |
6919 | 6928 |
6920 deferred->set_is_dont_delete(is_dont_delete); | 6929 deferred->set_is_dont_delete(is_dont_delete); |
6921 | 6930 |
6922 if (!is_dont_delete) { | 6931 if (!is_dont_delete) { |
6923 #ifdef DEBUG | 6932 #ifdef DEBUG |
6924 InlinedNamedLoadInstructions += 3; | 6933 InlinedNamedLoadInstructions += 3; |
6925 #endif | 6934 #endif |
6926 __ cmp(receiver, Operand(Factory::the_hole_value())); | 6935 __ cmp(receiver, Operand(FACTORY->the_hole_value())); |
6927 deferred->Branch(eq); | 6936 deferred->Branch(eq); |
6928 } else if (FLAG_debug_code) { | 6937 } else if (FLAG_debug_code) { |
6929 #ifdef DEBUG | 6938 #ifdef DEBUG |
6930 InlinedNamedLoadInstructions += 3; | 6939 InlinedNamedLoadInstructions += 3; |
6931 #endif | 6940 #endif |
6932 __ cmp(receiver, Operand(Factory::the_hole_value())); | 6941 __ cmp(receiver, Operand(FACTORY->the_hole_value())); |
6933 __ b(&check_the_hole, eq); | 6942 __ b(&check_the_hole, eq); |
6934 __ bind(&cont); | 6943 __ bind(&cont); |
6935 } | 6944 } |
6936 } else { | 6945 } else { |
6937 // Initially use an invalid index. The index will be patched by the | 6946 // Initially use an invalid index. The index will be patched by the |
6938 // inline cache code. | 6947 // inline cache code. |
6939 __ ldr(receiver, MemOperand(receiver, 0)); | 6948 __ ldr(receiver, MemOperand(receiver, 0)); |
6940 } | 6949 } |
6941 | 6950 |
6942 // Make sure that the expected number of instructions are generated. | 6951 // Make sure that the expected number of instructions are generated. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6990 Register scratch1 = VirtualFrame::scratch1(); | 6999 Register scratch1 = VirtualFrame::scratch1(); |
6991 | 7000 |
6992 // Check the map. Initially use an invalid map to force a | 7001 // Check the map. Initially use an invalid map to force a |
6993 // failure. The map check will be patched in the runtime system. | 7002 // failure. The map check will be patched in the runtime system. |
6994 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 7003 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
6995 | 7004 |
6996 #ifdef DEBUG | 7005 #ifdef DEBUG |
6997 Label check_inlined_codesize; | 7006 Label check_inlined_codesize; |
6998 masm_->bind(&check_inlined_codesize); | 7007 masm_->bind(&check_inlined_codesize); |
6999 #endif | 7008 #endif |
7000 __ mov(scratch0, Operand(Factory::null_value())); | 7009 __ mov(scratch0, Operand(FACTORY->null_value())); |
7001 __ cmp(scratch0, scratch1); | 7010 __ cmp(scratch0, scratch1); |
7002 deferred->Branch(ne); | 7011 deferred->Branch(ne); |
7003 | 7012 |
7004 int offset = 0; | 7013 int offset = 0; |
7005 __ str(value, MemOperand(receiver, offset)); | 7014 __ str(value, MemOperand(receiver, offset)); |
7006 | 7015 |
7007 // Update the write barrier and record its size. We do not use | 7016 // Update the write barrier and record its size. We do not use |
7008 // the RecordWrite macro here because we want the offset | 7017 // the RecordWrite macro here because we want the offset |
7009 // addition instruction first to make it easy to patch. | 7018 // addition instruction first to make it easy to patch. |
7010 Label record_write_start, record_write_done; | 7019 Label record_write_start, record_write_done; |
7011 __ bind(&record_write_start); | 7020 __ bind(&record_write_start); |
7012 // Add offset into the object. | 7021 // Add offset into the object. |
7013 __ add(scratch0, receiver, Operand(offset)); | 7022 __ add(scratch0, receiver, Operand(offset)); |
7014 // Test that the object is not in the new space. We cannot set | 7023 // Test that the object is not in the new space. We cannot set |
7015 // region marks for new space pages. | 7024 // region marks for new space pages. |
7016 __ InNewSpace(receiver, scratch1, eq, &record_write_done); | 7025 __ InNewSpace(receiver, scratch1, eq, &record_write_done); |
7017 // Record the actual write. | 7026 // Record the actual write. |
7018 __ RecordWriteHelper(receiver, scratch0, scratch1); | 7027 __ RecordWriteHelper(receiver, scratch0, scratch1); |
7019 __ bind(&record_write_done); | 7028 __ bind(&record_write_done); |
7020 // Clobber all input registers when running with the debug-code flag | 7029 // Clobber all input registers when running with the debug-code flag |
7021 // turned on to provoke errors. | 7030 // turned on to provoke errors. |
7022 if (FLAG_debug_code) { | 7031 if (FLAG_debug_code) { |
7023 __ mov(receiver, Operand(BitCast<int32_t>(kZapValue))); | 7032 __ mov(receiver, Operand(BitCast<int32_t>(kZapValue))); |
7024 __ mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); | 7033 __ mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); |
7025 __ mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); | 7034 __ mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); |
7026 } | 7035 } |
7027 // Check that this is the first inlined write barrier or that | 7036 // Check that this is the first inlined write barrier or that |
7028 // this inlined write barrier has the same size as all the other | 7037 // this inlined write barrier has the same size as all the other |
7029 // inlined write barriers. | 7038 // inlined write barriers. |
7030 ASSERT((inlined_write_barrier_size_ == -1) || | 7039 ASSERT((Isolate::Current()->inlined_write_barrier_size() == -1) || |
7031 (inlined_write_barrier_size_ == | 7040 (Isolate::Current()->inlined_write_barrier_size() == |
7032 masm()->InstructionsGeneratedSince(&record_write_start))); | 7041 masm()->InstructionsGeneratedSince(&record_write_start))); |
7033 inlined_write_barrier_size_ = | 7042 Isolate::Current()->set_inlined_write_barrier_size( |
7034 masm()->InstructionsGeneratedSince(&record_write_start); | 7043 masm()->InstructionsGeneratedSince(&record_write_start)); |
7035 | 7044 |
7036 // Make sure that the expected number of instructions are generated. | 7045 // Make sure that the expected number of instructions are generated. |
7037 ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(), | 7046 ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(), |
7038 masm()->InstructionsGeneratedSince(&check_inlined_codesize)); | 7047 masm()->InstructionsGeneratedSince(&check_inlined_codesize)); |
7039 } | 7048 } |
7040 deferred->BindExit(); | 7049 deferred->BindExit(); |
7041 } | 7050 } |
7042 ASSERT_EQ(expected_height, frame()->height()); | 7051 ASSERT_EQ(expected_height, frame()->height()); |
7043 } | 7052 } |
7044 | 7053 |
7045 | 7054 |
7046 void CodeGenerator::EmitKeyedLoad() { | 7055 void CodeGenerator::EmitKeyedLoad() { |
7047 if (loop_nesting() == 0) { | 7056 if (loop_nesting() == 0) { |
7048 Comment cmnt(masm_, "[ Load from keyed property"); | 7057 Comment cmnt(masm_, "[ Load from keyed property"); |
7049 frame_->CallKeyedLoadIC(); | 7058 frame_->CallKeyedLoadIC(); |
7050 } else { | 7059 } else { |
7051 // Inline the keyed load. | 7060 // Inline the keyed load. |
7052 Comment cmnt(masm_, "[ Inlined load from keyed property"); | 7061 Comment cmnt(masm_, "[ Inlined load from keyed property"); |
7053 | 7062 |
7054 // Counter will be decremented in the deferred code. Placed here to avoid | 7063 // Counter will be decremented in the deferred code. Placed here to avoid |
7055 // having it in the instruction stream below where patching will occur. | 7064 // having it in the instruction stream below where patching will occur. |
7056 __ IncrementCounter(&Counters::keyed_load_inline, 1, | 7065 __ IncrementCounter(COUNTERS->keyed_load_inline(), 1, |
7057 frame_->scratch0(), frame_->scratch1()); | 7066 frame_->scratch0(), frame_->scratch1()); |
7058 | 7067 |
7059 // Load the key and receiver from the stack. | 7068 // Load the key and receiver from the stack. |
7060 bool key_is_known_smi = frame_->KnownSmiAt(0); | 7069 bool key_is_known_smi = frame_->KnownSmiAt(0); |
7061 Register key = frame_->PopToRegister(); | 7070 Register key = frame_->PopToRegister(); |
7062 Register receiver = frame_->PopToRegister(key); | 7071 Register receiver = frame_->PopToRegister(key); |
7063 | 7072 |
7064 // The deferred code expects key and receiver in registers. | 7073 // The deferred code expects key and receiver in registers. |
7065 DeferredReferenceGetKeyedValue* deferred = | 7074 DeferredReferenceGetKeyedValue* deferred = |
7066 new DeferredReferenceGetKeyedValue(key, receiver); | 7075 new DeferredReferenceGetKeyedValue(key, receiver); |
(...skipping 16 matching lines...) Expand all Loading... |
7083 // Check that the key is a smi. | 7092 // Check that the key is a smi. |
7084 if (!key_is_known_smi) { | 7093 if (!key_is_known_smi) { |
7085 __ tst(key, Operand(kSmiTagMask)); | 7094 __ tst(key, Operand(kSmiTagMask)); |
7086 deferred->Branch(ne); | 7095 deferred->Branch(ne); |
7087 } | 7096 } |
7088 | 7097 |
7089 #ifdef DEBUG | 7098 #ifdef DEBUG |
7090 Label check_inlined_codesize; | 7099 Label check_inlined_codesize; |
7091 masm_->bind(&check_inlined_codesize); | 7100 masm_->bind(&check_inlined_codesize); |
7092 #endif | 7101 #endif |
7093 __ mov(scratch2, Operand(Factory::null_value())); | 7102 __ mov(scratch2, Operand(FACTORY->null_value())); |
7094 __ cmp(scratch1, scratch2); | 7103 __ cmp(scratch1, scratch2); |
7095 deferred->Branch(ne); | 7104 deferred->Branch(ne); |
7096 | 7105 |
7097 // Get the elements array from the receiver. | 7106 // Get the elements array from the receiver. |
7098 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 7107 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
7099 __ AssertFastElements(scratch1); | 7108 __ AssertFastElements(scratch1); |
7100 | 7109 |
7101 // Check that key is within bounds. Use unsigned comparison to handle | 7110 // Check that key is within bounds. Use unsigned comparison to handle |
7102 // negative keys. | 7111 // negative keys. |
7103 __ ldr(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); | 7112 __ ldr(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); |
(...skipping 29 matching lines...) Expand all Loading... |
7133 if (loop_nesting() > 0 && key_type->IsLikelySmi()) { | 7142 if (loop_nesting() > 0 && key_type->IsLikelySmi()) { |
7134 // Inline the keyed store. | 7143 // Inline the keyed store. |
7135 Comment cmnt(masm_, "[ Inlined store to keyed property"); | 7144 Comment cmnt(masm_, "[ Inlined store to keyed property"); |
7136 | 7145 |
7137 Register scratch1 = VirtualFrame::scratch0(); | 7146 Register scratch1 = VirtualFrame::scratch0(); |
7138 Register scratch2 = VirtualFrame::scratch1(); | 7147 Register scratch2 = VirtualFrame::scratch1(); |
7139 Register scratch3 = r3; | 7148 Register scratch3 = r3; |
7140 | 7149 |
7141 // Counter will be decremented in the deferred code. Placed here to avoid | 7150 // Counter will be decremented in the deferred code. Placed here to avoid |
7142 // having it in the instruction stream below where patching will occur. | 7151 // having it in the instruction stream below where patching will occur. |
7143 __ IncrementCounter(&Counters::keyed_store_inline, 1, | 7152 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1, |
7144 scratch1, scratch2); | 7153 scratch1, scratch2); |
7145 | 7154 |
7146 | 7155 |
7147 // Load the value, key and receiver from the stack. | 7156 // Load the value, key and receiver from the stack. |
7148 bool value_is_harmless = frame_->KnownSmiAt(0); | 7157 bool value_is_harmless = frame_->KnownSmiAt(0); |
7149 if (wb_info == NEVER_NEWSPACE) value_is_harmless = true; | 7158 if (wb_info == NEVER_NEWSPACE) value_is_harmless = true; |
7150 bool key_is_smi = frame_->KnownSmiAt(1); | 7159 bool key_is_smi = frame_->KnownSmiAt(1); |
7151 Register value = frame_->PopToRegister(); | 7160 Register value = frame_->PopToRegister(); |
7152 Register key = frame_->PopToRegister(value); | 7161 Register key = frame_->PopToRegister(value); |
7153 VirtualFrame::SpilledScope spilled(frame_); | 7162 VirtualFrame::SpilledScope spilled(frame_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7214 #ifdef DEBUG | 7223 #ifdef DEBUG |
7215 Label check_inlined_codesize; | 7224 Label check_inlined_codesize; |
7216 masm_->bind(&check_inlined_codesize); | 7225 masm_->bind(&check_inlined_codesize); |
7217 #endif | 7226 #endif |
7218 | 7227 |
7219 // Read the fixed array map from the constant pool (not from the root | 7228 // Read the fixed array map from the constant pool (not from the root |
7220 // array) so that the value can be patched. When debugging, we patch this | 7229 // array) so that the value can be patched. When debugging, we patch this |
7221 // comparison to always fail so that we will hit the IC call in the | 7230 // comparison to always fail so that we will hit the IC call in the |
7222 // deferred code which will allow the debugger to break for fast case | 7231 // deferred code which will allow the debugger to break for fast case |
7223 // stores. | 7232 // stores. |
7224 __ mov(scratch3, Operand(Factory::fixed_array_map())); | 7233 __ mov(scratch3, Operand(FACTORY->fixed_array_map())); |
7225 __ cmp(scratch2, scratch3); | 7234 __ cmp(scratch2, scratch3); |
7226 deferred->Branch(ne); | 7235 deferred->Branch(ne); |
7227 | 7236 |
7228 // Check that the key is within bounds. Both the key and the length of | 7237 // Check that the key is within bounds. Both the key and the length of |
7229 // the JSArray are smis (because the fixed array check above ensures the | 7238 // the JSArray are smis (because the fixed array check above ensures the |
7230 // elements are in fast case). Use unsigned comparison to handle negative | 7239 // elements are in fast case). Use unsigned comparison to handle negative |
7231 // keys. | 7240 // keys. |
7232 __ ldr(scratch3, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 7241 __ ldr(scratch3, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
7233 __ cmp(scratch3, key); | 7242 __ cmp(scratch3, key); |
7234 deferred->Branch(ls); // Unsigned less equal. | 7243 deferred->Branch(ls); // Unsigned less equal. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7384 | 7393 |
7385 default: | 7394 default: |
7386 UNREACHABLE(); | 7395 UNREACHABLE(); |
7387 } | 7396 } |
7388 } | 7397 } |
7389 | 7398 |
7390 | 7399 |
7391 const char* GenericBinaryOpStub::GetName() { | 7400 const char* GenericBinaryOpStub::GetName() { |
7392 if (name_ != NULL) return name_; | 7401 if (name_ != NULL) return name_; |
7393 const int len = 100; | 7402 const int len = 100; |
7394 name_ = Bootstrapper::AllocateAutoDeletedArray(len); | 7403 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(len); |
7395 if (name_ == NULL) return "OOM"; | 7404 if (name_ == NULL) return "OOM"; |
7396 const char* op_name = Token::Name(op_); | 7405 const char* op_name = Token::Name(op_); |
7397 const char* overwrite_name; | 7406 const char* overwrite_name; |
7398 switch (mode_) { | 7407 switch (mode_) { |
7399 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 7408 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
7400 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 7409 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
7401 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; | 7410 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
7402 default: overwrite_name = "UnknownOverwrite"; break; | 7411 default: overwrite_name = "UnknownOverwrite"; break; |
7403 } | 7412 } |
7404 | 7413 |
7405 OS::SNPrintF(Vector<char>(name_, len), | 7414 OS::SNPrintF(Vector<char>(name_, len), |
7406 "GenericBinaryOpStub_%s_%s%s_%s", | 7415 "GenericBinaryOpStub_%s_%s%s_%s", |
7407 op_name, | 7416 op_name, |
7408 overwrite_name, | 7417 overwrite_name, |
7409 specialized_on_rhs_ ? "_ConstantRhs" : "", | 7418 specialized_on_rhs_ ? "_ConstantRhs" : "", |
7410 BinaryOpIC::GetName(runtime_operands_type_)); | 7419 BinaryOpIC::GetName(runtime_operands_type_)); |
7411 return name_; | 7420 return name_; |
7412 } | 7421 } |
7413 | 7422 |
7414 | |
7415 #undef __ | 7423 #undef __ |
7416 | 7424 |
7417 } } // namespace v8::internal | 7425 } } // namespace v8::internal |
7418 | 7426 |
7419 #endif // V8_TARGET_ARCH_ARM | 7427 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |