| OLD | NEW |
| 1 // Copyright 2010 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2741 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 2741 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 2742 // Call the runtime to declare the globals. The inevitable call | 2742 // Call the runtime to declare the globals. The inevitable call |
| 2743 // will sync frame elements to memory anyway, so we do it eagerly to | 2743 // will sync frame elements to memory anyway, so we do it eagerly to |
| 2744 // allow us to push the arguments directly into place. | 2744 // allow us to push the arguments directly into place. |
| 2745 frame_->SyncRange(0, frame_->element_count() - 1); | 2745 frame_->SyncRange(0, frame_->element_count() - 1); |
| 2746 | 2746 |
| 2747 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); | 2747 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); |
| 2748 frame_->EmitPush(rsi); // The context is the first argument. | 2748 frame_->EmitPush(rsi); // The context is the first argument. |
| 2749 frame_->EmitPush(kScratchRegister); | 2749 frame_->EmitPush(kScratchRegister); |
| 2750 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); | 2750 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); |
| 2751 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 2751 frame_->EmitPush(Smi::FromInt(strict_mode_flag())); |
| 2752 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4); |
| 2752 // Return value is ignored. | 2753 // Return value is ignored. |
| 2753 } | 2754 } |
| 2754 | 2755 |
| 2755 | 2756 |
| 2756 void CodeGenerator::VisitDeclaration(Declaration* node) { | 2757 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 2757 Comment cmnt(masm_, "[ Declaration"); | 2758 Comment cmnt(masm_, "[ Declaration"); |
| 2758 Variable* var = node->proxy()->var(); | 2759 Variable* var = node->proxy()->var(); |
| 2759 ASSERT(var != NULL); // must have been resolved | 2760 ASSERT(var != NULL); // must have been resolved |
| 2760 Slot* slot = var->AsSlot(); | 2761 Slot* slot = var->AsSlot(); |
| 2761 | 2762 |
| (...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4599 // context slot declaration, but we cannot initialize it at the same | 4600 // context slot declaration, but we cannot initialize it at the same |
| 4600 // time, because the const declaration may be at the end of the eval | 4601 // time, because the const declaration may be at the end of the eval |
| 4601 // code (sigh...) and the const variable may have been used before | 4602 // code (sigh...) and the const variable may have been used before |
| 4602 // (where its value is 'undefined'). Thus, we can only do the | 4603 // (where its value is 'undefined'). Thus, we can only do the |
| 4603 // initialization when we actually encounter the expression and when | 4604 // initialization when we actually encounter the expression and when |
| 4604 // the expression operands are defined and valid, and thus we need the | 4605 // the expression operands are defined and valid, and thus we need the |
| 4605 // split into 2 operations: declaration of the context slot followed | 4606 // split into 2 operations: declaration of the context slot followed |
| 4606 // by initialization. | 4607 // by initialization. |
| 4607 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 4608 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 4608 } else { | 4609 } else { |
| 4609 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); | 4610 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 4611 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4); |
| 4610 } | 4612 } |
| 4611 // Storing a variable must keep the (new) value on the expression | 4613 // Storing a variable must keep the (new) value on the expression |
| 4612 // stack. This is necessary for compiling chained assignment | 4614 // stack. This is necessary for compiling chained assignment |
| 4613 // expressions. | 4615 // expressions. |
| 4614 frame_->Push(&value); | 4616 frame_->Push(&value); |
| 4615 } else { | 4617 } else { |
| 4616 ASSERT(!slot->var()->is_dynamic()); | 4618 ASSERT(!slot->var()->is_dynamic()); |
| 4617 | 4619 |
| 4618 JumpTarget exit; | 4620 JumpTarget exit; |
| 4619 if (init_state == CONST_INIT) { | 4621 if (init_state == CONST_INIT) { |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4888 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 4890 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
| 4889 // else fall through. | 4891 // else fall through. |
| 4890 case ObjectLiteral::Property::COMPUTED: { | 4892 case ObjectLiteral::Property::COMPUTED: { |
| 4891 Handle<Object> key(property->key()->handle()); | 4893 Handle<Object> key(property->key()->handle()); |
| 4892 if (key->IsSymbol()) { | 4894 if (key->IsSymbol()) { |
| 4893 // Duplicate the object as the IC receiver. | 4895 // Duplicate the object as the IC receiver. |
| 4894 frame_->Dup(); | 4896 frame_->Dup(); |
| 4895 Load(property->value()); | 4897 Load(property->value()); |
| 4896 if (property->emit_store()) { | 4898 if (property->emit_store()) { |
| 4897 Result ignored = | 4899 Result ignored = |
| 4898 frame_->CallStoreIC(Handle<String>::cast(key), false); | 4900 frame_->CallStoreIC(Handle<String>::cast(key), false, |
| 4901 strict_mode_flag()); |
| 4899 // A test rax instruction following the store IC call would | 4902 // A test rax instruction following the store IC call would |
| 4900 // indicate the presence of an inlined version of the | 4903 // indicate the presence of an inlined version of the |
| 4901 // store. Add a nop to indicate that there is no such | 4904 // store. Add a nop to indicate that there is no such |
| 4902 // inlined version. | 4905 // inlined version. |
| 4903 __ nop(); | 4906 __ nop(); |
| 4904 } else { | 4907 } else { |
| 4905 frame_->Drop(2); | 4908 frame_->Drop(2); |
| 4906 } | 4909 } |
| 4907 break; | 4910 break; |
| 4908 } | 4911 } |
| 4909 // Fall through | 4912 // Fall through |
| 4910 } | 4913 } |
| 4911 case ObjectLiteral::Property::PROTOTYPE: { | 4914 case ObjectLiteral::Property::PROTOTYPE: { |
| 4912 // Duplicate the object as an argument to the runtime call. | 4915 // Duplicate the object as an argument to the runtime call. |
| 4913 frame_->Dup(); | 4916 frame_->Dup(); |
| 4914 Load(property->key()); | 4917 Load(property->key()); |
| 4915 Load(property->value()); | 4918 Load(property->value()); |
| 4916 if (property->emit_store()) { | 4919 if (property->emit_store()) { |
| 4920 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 4917 // Ignore the result. | 4921 // Ignore the result. |
| 4918 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); | 4922 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4); |
| 4919 } else { | 4923 } else { |
| 4920 frame_->Drop(3); | 4924 frame_->Drop(3); |
| 4921 } | 4925 } |
| 4922 break; | 4926 break; |
| 4923 } | 4927 } |
| 4924 case ObjectLiteral::Property::SETTER: { | 4928 case ObjectLiteral::Property::SETTER: { |
| 4925 // Duplicate the object as an argument to the runtime call. | 4929 // Duplicate the object as an argument to the runtime call. |
| 4926 frame_->Dup(); | 4930 frame_->Dup(); |
| 4927 Load(property->key()); | 4931 Load(property->key()); |
| 4928 frame_->Push(Smi::FromInt(1)); | 4932 frame_->Push(Smi::FromInt(1)); |
| (...skipping 2094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7023 answer = frame()->CallRuntime(Runtime::kMath_pow_cfunction, 2); | 7027 answer = frame()->CallRuntime(Runtime::kMath_pow_cfunction, 2); |
| 7024 | 7028 |
| 7025 done.Bind(&answer); | 7029 done.Bind(&answer); |
| 7026 frame()->Push(&answer); | 7030 frame()->Push(&answer); |
| 7027 } | 7031 } |
| 7028 | 7032 |
| 7029 | 7033 |
| 7030 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 7034 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 7031 ASSERT_EQ(args->length(), 1); | 7035 ASSERT_EQ(args->length(), 1); |
| 7032 Load(args->at(0)); | 7036 Load(args->at(0)); |
| 7033 TranscendentalCacheStub stub(TranscendentalCache::SIN); | 7037 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 7038 TranscendentalCacheStub::TAGGED); |
| 7034 Result result = frame_->CallStub(&stub, 1); | 7039 Result result = frame_->CallStub(&stub, 1); |
| 7035 frame_->Push(&result); | 7040 frame_->Push(&result); |
| 7036 } | 7041 } |
| 7037 | 7042 |
| 7038 | 7043 |
| 7039 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 7044 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 7040 ASSERT_EQ(args->length(), 1); | 7045 ASSERT_EQ(args->length(), 1); |
| 7041 Load(args->at(0)); | 7046 Load(args->at(0)); |
| 7042 TranscendentalCacheStub stub(TranscendentalCache::COS); | 7047 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 7048 TranscendentalCacheStub::TAGGED); |
| 7043 Result result = frame_->CallStub(&stub, 1); | 7049 Result result = frame_->CallStub(&stub, 1); |
| 7044 frame_->Push(&result); | 7050 frame_->Push(&result); |
| 7045 } | 7051 } |
| 7046 | 7052 |
| 7047 | 7053 |
| 7048 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { | 7054 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { |
| 7049 ASSERT_EQ(args->length(), 1); | 7055 ASSERT_EQ(args->length(), 1); |
| 7050 Load(args->at(0)); | 7056 Load(args->at(0)); |
| 7051 TranscendentalCacheStub stub(TranscendentalCache::LOG); | 7057 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 7058 TranscendentalCacheStub::TAGGED); |
| 7052 Result result = frame_->CallStub(&stub, 1); | 7059 Result result = frame_->CallStub(&stub, 1); |
| 7053 frame_->Push(&result); | 7060 frame_->Push(&result); |
| 7054 } | 7061 } |
| 7055 | 7062 |
| 7056 | 7063 |
| 7057 // Generates the Math.sqrt method. Please note - this function assumes that | 7064 // Generates the Math.sqrt method. Please note - this function assumes that |
| 7058 // the callsite has executed ToNumber on the argument. | 7065 // the callsite has executed ToNumber on the argument. |
| 7059 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | 7066 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
| 7060 ASSERT(args->length() == 1); | 7067 ASSERT(args->length() == 1); |
| 7061 Load(args->at(0)); | 7068 Load(args->at(0)); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7223 destination()->Invert(); | 7230 destination()->Invert(); |
| 7224 LoadCondition(node->expression(), destination(), true); | 7231 LoadCondition(node->expression(), destination(), true); |
| 7225 // Swap the labels back. | 7232 // Swap the labels back. |
| 7226 destination()->Invert(); | 7233 destination()->Invert(); |
| 7227 | 7234 |
| 7228 } else if (op == Token::DELETE) { | 7235 } else if (op == Token::DELETE) { |
| 7229 Property* property = node->expression()->AsProperty(); | 7236 Property* property = node->expression()->AsProperty(); |
| 7230 if (property != NULL) { | 7237 if (property != NULL) { |
| 7231 Load(property->obj()); | 7238 Load(property->obj()); |
| 7232 Load(property->key()); | 7239 Load(property->key()); |
| 7233 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); | 7240 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 7241 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3); |
| 7234 frame_->Push(&answer); | 7242 frame_->Push(&answer); |
| 7235 return; | 7243 return; |
| 7236 } | 7244 } |
| 7237 | 7245 |
| 7238 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 7246 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 7239 if (variable != NULL) { | 7247 if (variable != NULL) { |
| 7248 // Delete of an unqualified identifier is disallowed in strict mode |
| 7249 // but "delete this" is. |
| 7250 ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this()); |
| 7240 Slot* slot = variable->AsSlot(); | 7251 Slot* slot = variable->AsSlot(); |
| 7241 if (variable->is_global()) { | 7252 if (variable->is_global()) { |
| 7242 LoadGlobal(); | 7253 LoadGlobal(); |
| 7243 frame_->Push(variable->name()); | 7254 frame_->Push(variable->name()); |
| 7255 frame_->Push(Smi::FromInt(kNonStrictMode)); |
| 7244 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | 7256 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
| 7245 CALL_FUNCTION, 2); | 7257 CALL_FUNCTION, 3); |
| 7246 frame_->Push(&answer); | 7258 frame_->Push(&answer); |
| 7247 return; | |
| 7248 | 7259 |
| 7249 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 7260 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 7250 // Call the runtime to delete from the context holding the named | 7261 // Call the runtime to delete from the context holding the named |
| 7251 // variable. Sync the virtual frame eagerly so we can push the | 7262 // variable. Sync the virtual frame eagerly so we can push the |
| 7252 // arguments directly into place. | 7263 // arguments directly into place. |
| 7253 frame_->SyncRange(0, frame_->element_count() - 1); | 7264 frame_->SyncRange(0, frame_->element_count() - 1); |
| 7254 frame_->EmitPush(rsi); | 7265 frame_->EmitPush(rsi); |
| 7255 frame_->EmitPush(variable->name()); | 7266 frame_->EmitPush(variable->name()); |
| 7256 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); | 7267 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 7257 frame_->Push(&answer); | 7268 frame_->Push(&answer); |
| 7258 return; | 7269 } else { |
| 7270 // Default: Result of deleting non-global, not dynamically |
| 7271 // introduced variables is false. |
| 7272 frame_->Push(FACTORY->false_value()); |
| 7259 } | 7273 } |
| 7260 | |
| 7261 // Default: Result of deleting non-global, not dynamically | |
| 7262 // introduced variables is false. | |
| 7263 frame_->Push(FACTORY->false_value()); | |
| 7264 | |
| 7265 } else { | 7274 } else { |
| 7266 // Default: Result of deleting expressions is true. | 7275 // Default: Result of deleting expressions is true. |
| 7267 Load(node->expression()); // may have side-effects | 7276 Load(node->expression()); // may have side-effects |
| 7268 frame_->SetElementAt(0, FACTORY->true_value()); | 7277 frame_->SetElementAt(0, FACTORY->true_value()); |
| 7269 } | 7278 } |
| 7270 | 7279 |
| 7271 } else if (op == Token::TYPEOF) { | 7280 } else if (op == Token::TYPEOF) { |
| 7272 // Special case for loading the typeof expression; see comment on | 7281 // Special case for loading the typeof expression; see comment on |
| 7273 // LoadTypeofExpression(). | 7282 // LoadTypeofExpression(). |
| 7274 LoadTypeofExpression(node->expression()); | 7283 LoadTypeofExpression(node->expression()); |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8065 __ IncrementCounter(COUNTERS->keyed_load_inline_miss(), 1); | 8074 __ IncrementCounter(COUNTERS->keyed_load_inline_miss(), 1); |
| 8066 | 8075 |
| 8067 if (!dst_.is(rax)) __ movq(dst_, rax); | 8076 if (!dst_.is(rax)) __ movq(dst_, rax); |
| 8068 } | 8077 } |
| 8069 | 8078 |
| 8070 | 8079 |
| 8071 class DeferredReferenceSetKeyedValue: public DeferredCode { | 8080 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 8072 public: | 8081 public: |
| 8073 DeferredReferenceSetKeyedValue(Register value, | 8082 DeferredReferenceSetKeyedValue(Register value, |
| 8074 Register key, | 8083 Register key, |
| 8075 Register receiver) | 8084 Register receiver, |
| 8076 : value_(value), key_(key), receiver_(receiver) { | 8085 StrictModeFlag strict_mode) |
| 8086 : value_(value), |
| 8087 key_(key), |
| 8088 receiver_(receiver), |
| 8089 strict_mode_(strict_mode) { |
| 8077 set_comment("[ DeferredReferenceSetKeyedValue"); | 8090 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 8078 } | 8091 } |
| 8079 | 8092 |
| 8080 virtual void Generate(); | 8093 virtual void Generate(); |
| 8081 | 8094 |
| 8082 Label* patch_site() { return &patch_site_; } | 8095 Label* patch_site() { return &patch_site_; } |
| 8083 | 8096 |
| 8084 private: | 8097 private: |
| 8085 Register value_; | 8098 Register value_; |
| 8086 Register key_; | 8099 Register key_; |
| 8087 Register receiver_; | 8100 Register receiver_; |
| 8088 Label patch_site_; | 8101 Label patch_site_; |
| 8102 StrictModeFlag strict_mode_; |
| 8089 }; | 8103 }; |
| 8090 | 8104 |
| 8091 | 8105 |
| 8092 void DeferredReferenceSetKeyedValue::Generate() { | 8106 void DeferredReferenceSetKeyedValue::Generate() { |
| 8093 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), 1); | 8107 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), 1); |
| 8094 // Move value, receiver, and key to registers rax, rdx, and rcx, as | 8108 // Move value, receiver, and key to registers rax, rdx, and rcx, as |
| 8095 // the IC stub expects. | 8109 // the IC stub expects. |
| 8096 // Move value to rax, using xchg if the receiver or key is in rax. | 8110 // Move value to rax, using xchg if the receiver or key is in rax. |
| 8097 if (!value_.is(rax)) { | 8111 if (!value_.is(rax)) { |
| 8098 if (!receiver_.is(rax) && !key_.is(rax)) { | 8112 if (!receiver_.is(rax) && !key_.is(rax)) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8131 } | 8145 } |
| 8132 } else if (key_.is(rcx)) { | 8146 } else if (key_.is(rcx)) { |
| 8133 __ movq(rdx, receiver_); | 8147 __ movq(rdx, receiver_); |
| 8134 } else { | 8148 } else { |
| 8135 __ movq(rcx, key_); | 8149 __ movq(rcx, key_); |
| 8136 __ movq(rdx, receiver_); | 8150 __ movq(rdx, receiver_); |
| 8137 } | 8151 } |
| 8138 | 8152 |
| 8139 // Call the IC stub. | 8153 // Call the IC stub. |
| 8140 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 8154 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 8141 Builtins::KeyedStoreIC_Initialize)); | 8155 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict |
| 8156 : Builtins::KeyedStoreIC_Initialize)); |
| 8142 __ Call(ic, RelocInfo::CODE_TARGET); | 8157 __ Call(ic, RelocInfo::CODE_TARGET); |
| 8143 // The delta from the start of the map-compare instructions (initial movq) | 8158 // The delta from the start of the map-compare instructions (initial movq) |
| 8144 // to the test instruction. We use masm_-> directly here instead of the | 8159 // to the test instruction. We use masm_-> directly here instead of the |
| 8145 // __ macro because the macro sometimes uses macro expansion to turn | 8160 // __ macro because the macro sometimes uses macro expansion to turn |
| 8146 // into something that can't return a value. This is encountered | 8161 // into something that can't return a value. This is encountered |
| 8147 // when doing generated code coverage tests. | 8162 // when doing generated code coverage tests. |
| 8148 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 8163 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
| 8149 // Here we use masm_-> instead of the __ macro because this is the | 8164 // Here we use masm_-> instead of the __ macro because this is the |
| 8150 // instruction that gets patched and coverage code gets in the way. | 8165 // instruction that gets patched and coverage code gets in the way. |
| 8151 masm_->testl(rax, Immediate(-delta_to_patch_site)); | 8166 masm_->testl(rax, Immediate(-delta_to_patch_site)); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8231 } | 8246 } |
| 8232 | 8247 |
| 8233 | 8248 |
| 8234 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { | 8249 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
| 8235 #ifdef DEBUG | 8250 #ifdef DEBUG |
| 8236 int expected_height = frame()->height() - (is_contextual ? 1 : 2); | 8251 int expected_height = frame()->height() - (is_contextual ? 1 : 2); |
| 8237 #endif | 8252 #endif |
| 8238 | 8253 |
| 8239 Result result; | 8254 Result result; |
| 8240 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { | 8255 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
| 8241 result = frame()->CallStoreIC(name, is_contextual); | 8256 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 8242 // A test rax instruction following the call signals that the inobject | 8257 // A test rax instruction following the call signals that the inobject |
| 8243 // property case was inlined. Ensure that there is not a test rax | 8258 // property case was inlined. Ensure that there is not a test rax |
| 8244 // instruction here. | 8259 // instruction here. |
| 8245 __ nop(); | 8260 __ nop(); |
| 8246 } else { | 8261 } else { |
| 8247 // Inline the in-object property case. | 8262 // Inline the in-object property case. |
| 8248 JumpTarget slow, done; | 8263 JumpTarget slow, done; |
| 8249 Label patch_site; | 8264 Label patch_site; |
| 8250 | 8265 |
| 8251 // Get the value and receiver from the stack. | 8266 // Get the value and receiver from the stack. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8331 } | 8346 } |
| 8332 __ bind(&skip_write_barrier); | 8347 __ bind(&skip_write_barrier); |
| 8333 value.Unuse(); | 8348 value.Unuse(); |
| 8334 scratch.Unuse(); | 8349 scratch.Unuse(); |
| 8335 receiver.Unuse(); | 8350 receiver.Unuse(); |
| 8336 done.Jump(&result); | 8351 done.Jump(&result); |
| 8337 | 8352 |
| 8338 slow.Bind(&value, &receiver); | 8353 slow.Bind(&value, &receiver); |
| 8339 frame()->Push(&receiver); | 8354 frame()->Push(&receiver); |
| 8340 frame()->Push(&value); | 8355 frame()->Push(&value); |
| 8341 result = frame()->CallStoreIC(name, is_contextual); | 8356 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 8342 // Encode the offset to the map check instruction and the offset | 8357 // Encode the offset to the map check instruction and the offset |
| 8343 // to the write barrier store address computation in a test rax | 8358 // to the write barrier store address computation in a test rax |
| 8344 // instruction. | 8359 // instruction. |
| 8345 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); | 8360 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); |
| 8346 __ testl(rax, | 8361 __ testl(rax, |
| 8347 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); | 8362 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); |
| 8348 done.Bind(&result); | 8363 done.Bind(&result); |
| 8349 } | 8364 } |
| 8350 | 8365 |
| 8351 ASSERT_EQ(expected_height, frame()->height()); | 8366 ASSERT_EQ(expected_height, frame()->height()); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8472 bool value_is_constant = result.is_constant(); | 8487 bool value_is_constant = result.is_constant(); |
| 8473 | 8488 |
| 8474 // Make sure that value, key and receiver are in registers. | 8489 // Make sure that value, key and receiver are in registers. |
| 8475 result.ToRegister(); | 8490 result.ToRegister(); |
| 8476 key.ToRegister(); | 8491 key.ToRegister(); |
| 8477 receiver.ToRegister(); | 8492 receiver.ToRegister(); |
| 8478 | 8493 |
| 8479 DeferredReferenceSetKeyedValue* deferred = | 8494 DeferredReferenceSetKeyedValue* deferred = |
| 8480 new DeferredReferenceSetKeyedValue(result.reg(), | 8495 new DeferredReferenceSetKeyedValue(result.reg(), |
| 8481 key.reg(), | 8496 key.reg(), |
| 8482 receiver.reg()); | 8497 receiver.reg(), |
| 8498 strict_mode_flag()); |
| 8483 | 8499 |
| 8484 // Check that the receiver is not a smi. | 8500 // Check that the receiver is not a smi. |
| 8485 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); | 8501 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); |
| 8486 | 8502 |
| 8487 // Check that the key is a smi. | 8503 // Check that the key is a smi. |
| 8488 if (!key.is_smi()) { | 8504 if (!key.is_smi()) { |
| 8489 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); | 8505 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); |
| 8490 } else if (FLAG_debug_code) { | 8506 } else if (FLAG_debug_code) { |
| 8491 __ AbortIfNotSmi(key.reg()); | 8507 __ AbortIfNotSmi(key.reg()); |
| 8492 } | 8508 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8534 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); | 8550 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); |
| 8535 __ movq(FieldOperand(tmp.reg(), | 8551 __ movq(FieldOperand(tmp.reg(), |
| 8536 index.reg, | 8552 index.reg, |
| 8537 index.scale, | 8553 index.scale, |
| 8538 FixedArray::kHeaderSize), | 8554 FixedArray::kHeaderSize), |
| 8539 result.reg()); | 8555 result.reg()); |
| 8540 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1); | 8556 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1); |
| 8541 | 8557 |
| 8542 deferred->BindExit(); | 8558 deferred->BindExit(); |
| 8543 } else { | 8559 } else { |
| 8544 result = frame()->CallKeyedStoreIC(); | 8560 result = frame()->CallKeyedStoreIC(strict_mode_flag()); |
| 8545 // Make sure that we do not have a test instruction after the | 8561 // Make sure that we do not have a test instruction after the |
| 8546 // call. A test instruction after the call is used to | 8562 // call. A test instruction after the call is used to |
| 8547 // indicate that we have generated an inline version of the | 8563 // indicate that we have generated an inline version of the |
| 8548 // keyed store. | 8564 // keyed store. |
| 8549 __ nop(); | 8565 __ nop(); |
| 8550 } | 8566 } |
| 8551 ASSERT(frame()->height() == original_height - 3); | 8567 ASSERT(frame()->height() == original_height - 3); |
| 8552 return result; | 8568 return result; |
| 8553 } | 8569 } |
| 8554 | 8570 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8813 } | 8829 } |
| 8814 | 8830 |
| 8815 #endif | 8831 #endif |
| 8816 | 8832 |
| 8817 | 8833 |
| 8818 #undef __ | 8834 #undef __ |
| 8819 | 8835 |
| 8820 } } // namespace v8::internal | 8836 } } // namespace v8::internal |
| 8821 | 8837 |
| 8822 #endif // V8_TARGET_ARCH_X64 | 8838 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |