| 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 3513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3524 | 3524 |
| 3525 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 3525 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 3526 // Call the runtime to declare the globals. The inevitable call | 3526 // Call the runtime to declare the globals. The inevitable call |
| 3527 // will sync frame elements to memory anyway, so we do it eagerly to | 3527 // will sync frame elements to memory anyway, so we do it eagerly to |
| 3528 // allow us to push the arguments directly into place. | 3528 // allow us to push the arguments directly into place. |
| 3529 frame_->SyncRange(0, frame_->element_count() - 1); | 3529 frame_->SyncRange(0, frame_->element_count() - 1); |
| 3530 | 3530 |
| 3531 frame_->EmitPush(esi); // The context is the first argument. | 3531 frame_->EmitPush(esi); // The context is the first argument. |
| 3532 frame_->EmitPush(Immediate(pairs)); | 3532 frame_->EmitPush(Immediate(pairs)); |
| 3533 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); | 3533 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); |
| 3534 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 3534 frame_->EmitPush(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 3535 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4); |
| 3535 // Return value is ignored. | 3536 // Return value is ignored. |
| 3536 } | 3537 } |
| 3537 | 3538 |
| 3538 | 3539 |
| 3539 void CodeGenerator::VisitDeclaration(Declaration* node) { | 3540 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 3540 Comment cmnt(masm_, "[ Declaration"); | 3541 Comment cmnt(masm_, "[ Declaration"); |
| 3541 Variable* var = node->proxy()->var(); | 3542 Variable* var = node->proxy()->var(); |
| 3542 ASSERT(var != NULL); // must have been resolved | 3543 ASSERT(var != NULL); // must have been resolved |
| 3543 Slot* slot = var->AsSlot(); | 3544 Slot* slot = var->AsSlot(); |
| 3544 | 3545 |
| (...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5257 // context slot declaration, but we cannot initialize it at the same | 5258 // context slot declaration, but we cannot initialize it at the same |
| 5258 // time, because the const declaration may be at the end of the eval | 5259 // time, because the const declaration may be at the end of the eval |
| 5259 // code (sigh...) and the const variable may have been used before | 5260 // code (sigh...) and the const variable may have been used before |
| 5260 // (where its value is 'undefined'). Thus, we can only do the | 5261 // (where its value is 'undefined'). Thus, we can only do the |
| 5261 // initialization when we actually encounter the expression and when | 5262 // initialization when we actually encounter the expression and when |
| 5262 // the expression operands are defined and valid, and thus we need the | 5263 // the expression operands are defined and valid, and thus we need the |
| 5263 // split into 2 operations: declaration of the context slot followed | 5264 // split into 2 operations: declaration of the context slot followed |
| 5264 // by initialization. | 5265 // by initialization. |
| 5265 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 5266 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 5266 } else { | 5267 } else { |
| 5267 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); | 5268 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 5269 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4); |
| 5268 } | 5270 } |
| 5269 // Storing a variable must keep the (new) value on the expression | 5271 // Storing a variable must keep the (new) value on the expression |
| 5270 // stack. This is necessary for compiling chained assignment | 5272 // stack. This is necessary for compiling chained assignment |
| 5271 // expressions. | 5273 // expressions. |
| 5272 frame_->Push(&value); | 5274 frame_->Push(&value); |
| 5273 | 5275 |
| 5274 } else { | 5276 } else { |
| 5275 ASSERT(!slot->var()->is_dynamic()); | 5277 ASSERT(!slot->var()->is_dynamic()); |
| 5276 | 5278 |
| 5277 JumpTarget exit; | 5279 JumpTarget exit; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5358 ASSERT(var->is_global()); | 5360 ASSERT(var->is_global()); |
| 5359 ASSERT(!in_safe_int32_mode()); | 5361 ASSERT(!in_safe_int32_mode()); |
| 5360 Reference ref(this, node); | 5362 Reference ref(this, node); |
| 5361 ref.GetValue(); | 5363 ref.GetValue(); |
| 5362 } | 5364 } |
| 5363 } | 5365 } |
| 5364 | 5366 |
| 5365 | 5367 |
| 5366 void CodeGenerator::VisitLiteral(Literal* node) { | 5368 void CodeGenerator::VisitLiteral(Literal* node) { |
| 5367 Comment cmnt(masm_, "[ Literal"); | 5369 Comment cmnt(masm_, "[ Literal"); |
| 5368 if (in_safe_int32_mode()) { | 5370 if (frame_->ConstantPoolOverflowed()) { |
| 5369 frame_->PushUntaggedElement(node->handle()); | 5371 Result temp = allocator_->Allocate(); |
| 5372 ASSERT(temp.is_valid()); |
| 5373 if (in_safe_int32_mode()) { |
| 5374 temp.set_untagged_int32(true); |
| 5375 } |
| 5376 __ Set(temp.reg(), Immediate(node->handle())); |
| 5377 frame_->Push(&temp); |
| 5370 } else { | 5378 } else { |
| 5371 frame_->Push(node->handle()); | 5379 if (in_safe_int32_mode()) { |
| 5380 frame_->PushUntaggedElement(node->handle()); |
| 5381 } else { |
| 5382 frame_->Push(node->handle()); |
| 5383 } |
| 5372 } | 5384 } |
| 5373 } | 5385 } |
| 5374 | 5386 |
| 5375 | 5387 |
| 5376 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) { | 5388 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) { |
| 5377 ASSERT(value->IsSmi()); | 5389 ASSERT(value->IsSmi()); |
| 5378 int bits = reinterpret_cast<int>(*value); | 5390 int bits = reinterpret_cast<int>(*value); |
| 5379 __ push(Immediate(bits ^ jit_cookie_)); | 5391 __ push(Immediate(bits ^ jit_cookie_)); |
| 5380 __ xor_(Operand(esp, 0), Immediate(jit_cookie_)); | 5392 __ xor_(Operand(esp, 0), Immediate(jit_cookie_)); |
| 5381 } | 5393 } |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5586 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 5598 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
| 5587 // else fall through. | 5599 // else fall through. |
| 5588 case ObjectLiteral::Property::COMPUTED: { | 5600 case ObjectLiteral::Property::COMPUTED: { |
| 5589 Handle<Object> key(property->key()->handle()); | 5601 Handle<Object> key(property->key()->handle()); |
| 5590 if (key->IsSymbol()) { | 5602 if (key->IsSymbol()) { |
| 5591 // Duplicate the object as the IC receiver. | 5603 // Duplicate the object as the IC receiver. |
| 5592 frame_->Dup(); | 5604 frame_->Dup(); |
| 5593 Load(property->value()); | 5605 Load(property->value()); |
| 5594 if (property->emit_store()) { | 5606 if (property->emit_store()) { |
| 5595 Result ignored = | 5607 Result ignored = |
| 5596 frame_->CallStoreIC(Handle<String>::cast(key), false); | 5608 frame_->CallStoreIC(Handle<String>::cast(key), false, |
| 5609 strict_mode_flag()); |
| 5597 // A test eax instruction following the store IC call would | 5610 // A test eax instruction following the store IC call would |
| 5598 // indicate the presence of an inlined version of the | 5611 // indicate the presence of an inlined version of the |
| 5599 // store. Add a nop to indicate that there is no such | 5612 // store. Add a nop to indicate that there is no such |
| 5600 // inlined version. | 5613 // inlined version. |
| 5601 __ nop(); | 5614 __ nop(); |
| 5602 } else { | 5615 } else { |
| 5603 frame_->Drop(2); | 5616 frame_->Drop(2); |
| 5604 } | 5617 } |
| 5605 break; | 5618 break; |
| 5606 } | 5619 } |
| 5607 // Fall through | 5620 // Fall through |
| 5608 } | 5621 } |
| 5609 case ObjectLiteral::Property::PROTOTYPE: { | 5622 case ObjectLiteral::Property::PROTOTYPE: { |
| 5610 // Duplicate the object as an argument to the runtime call. | 5623 // Duplicate the object as an argument to the runtime call. |
| 5611 frame_->Dup(); | 5624 frame_->Dup(); |
| 5612 Load(property->key()); | 5625 Load(property->key()); |
| 5613 Load(property->value()); | 5626 Load(property->value()); |
| 5614 if (property->emit_store()) { | 5627 if (property->emit_store()) { |
| 5628 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 5615 // Ignore the result. | 5629 // Ignore the result. |
| 5616 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); | 5630 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4); |
| 5617 } else { | 5631 } else { |
| 5618 frame_->Drop(3); | 5632 frame_->Drop(3); |
| 5619 } | 5633 } |
| 5620 break; | 5634 break; |
| 5621 } | 5635 } |
| 5622 case ObjectLiteral::Property::SETTER: { | 5636 case ObjectLiteral::Property::SETTER: { |
| 5623 // Duplicate the object as an argument to the runtime call. | 5637 // Duplicate the object as an argument to the runtime call. |
| 5624 frame_->Dup(); | 5638 frame_->Dup(); |
| 5625 Load(property->key()); | 5639 Load(property->key()); |
| 5626 frame_->Push(Smi::FromInt(1)); | 5640 frame_->Push(Smi::FromInt(1)); |
| (...skipping 2595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8222 destination()->Invert(); | 8236 destination()->Invert(); |
| 8223 LoadCondition(node->expression(), destination(), true); | 8237 LoadCondition(node->expression(), destination(), true); |
| 8224 // Swap the labels back. | 8238 // Swap the labels back. |
| 8225 destination()->Invert(); | 8239 destination()->Invert(); |
| 8226 | 8240 |
| 8227 } else if (op == Token::DELETE) { | 8241 } else if (op == Token::DELETE) { |
| 8228 Property* property = node->expression()->AsProperty(); | 8242 Property* property = node->expression()->AsProperty(); |
| 8229 if (property != NULL) { | 8243 if (property != NULL) { |
| 8230 Load(property->obj()); | 8244 Load(property->obj()); |
| 8231 Load(property->key()); | 8245 Load(property->key()); |
| 8232 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); | 8246 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 8247 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3); |
| 8233 frame_->Push(&answer); | 8248 frame_->Push(&answer); |
| 8234 return; | 8249 return; |
| 8235 } | 8250 } |
| 8236 | 8251 |
| 8237 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 8252 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 8238 if (variable != NULL) { | 8253 if (variable != NULL) { |
| 8254 // Delete of an unqualified identifier is disallowed in strict mode |
| 8255 // but "delete this" is. |
| 8256 ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this()); |
| 8239 Slot* slot = variable->AsSlot(); | 8257 Slot* slot = variable->AsSlot(); |
| 8240 if (variable->is_global()) { | 8258 if (variable->is_global()) { |
| 8241 LoadGlobal(); | 8259 LoadGlobal(); |
| 8242 frame_->Push(variable->name()); | 8260 frame_->Push(variable->name()); |
| 8261 frame_->Push(Smi::FromInt(kNonStrictMode)); |
| 8243 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | 8262 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
| 8244 CALL_FUNCTION, 2); | 8263 CALL_FUNCTION, 3); |
| 8245 frame_->Push(&answer); | 8264 frame_->Push(&answer); |
| 8246 return; | |
| 8247 | 8265 |
| 8248 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 8266 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 8249 // Call the runtime to delete from the context holding the named | 8267 // Call the runtime to delete from the context holding the named |
| 8250 // variable. Sync the virtual frame eagerly so we can push the | 8268 // variable. Sync the virtual frame eagerly so we can push the |
| 8251 // arguments directly into place. | 8269 // arguments directly into place. |
| 8252 frame_->SyncRange(0, frame_->element_count() - 1); | 8270 frame_->SyncRange(0, frame_->element_count() - 1); |
| 8253 frame_->EmitPush(esi); | 8271 frame_->EmitPush(esi); |
| 8254 frame_->EmitPush(Immediate(variable->name())); | 8272 frame_->EmitPush(Immediate(variable->name())); |
| 8255 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); | 8273 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 8256 frame_->Push(&answer); | 8274 frame_->Push(&answer); |
| 8257 return; | 8275 } else { |
| 8276 // Default: Result of deleting non-global, not dynamically |
| 8277 // introduced variables is false. |
| 8278 frame_->Push(FACTORY->false_value()); |
| 8258 } | 8279 } |
| 8259 | |
| 8260 // Default: Result of deleting non-global, not dynamically | |
| 8261 // introduced variables is false. | |
| 8262 frame_->Push(FACTORY->false_value()); | |
| 8263 | |
| 8264 } else { | 8280 } else { |
| 8265 // Default: Result of deleting expressions is true. | 8281 // Default: Result of deleting expressions is true. |
| 8266 Load(node->expression()); // may have side-effects | 8282 Load(node->expression()); // may have side-effects |
| 8267 frame_->SetElementAt(0, FACTORY->true_value()); | 8283 frame_->SetElementAt(0, FACTORY->true_value()); |
| 8268 } | 8284 } |
| 8269 | 8285 |
| 8270 } else if (op == Token::TYPEOF) { | 8286 } else if (op == Token::TYPEOF) { |
| 8271 // Special case for loading the typeof expression; see comment on | 8287 // Special case for loading the typeof expression; see comment on |
| 8272 // LoadTypeofExpression(). | 8288 // LoadTypeofExpression(). |
| 8273 LoadTypeofExpression(node->expression()); | 8289 LoadTypeofExpression(node->expression()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 8295 if (in_safe_int32_mode()) { | 8311 if (in_safe_int32_mode()) { |
| 8296 Visit(node->expression()); | 8312 Visit(node->expression()); |
| 8297 Result value = frame_->Pop(); | 8313 Result value = frame_->Pop(); |
| 8298 ASSERT(value.is_untagged_int32()); | 8314 ASSERT(value.is_untagged_int32()); |
| 8299 // Registers containing an int32 value are not multiply used. | 8315 // Registers containing an int32 value are not multiply used. |
| 8300 ASSERT(!value.is_register() || !frame_->is_used(value.reg())); | 8316 ASSERT(!value.is_register() || !frame_->is_used(value.reg())); |
| 8301 value.ToRegister(); | 8317 value.ToRegister(); |
| 8302 switch (op) { | 8318 switch (op) { |
| 8303 case Token::SUB: { | 8319 case Token::SUB: { |
| 8304 __ neg(value.reg()); | 8320 __ neg(value.reg()); |
| 8321 frame_->Push(&value); |
| 8305 if (node->no_negative_zero()) { | 8322 if (node->no_negative_zero()) { |
| 8306 // -MIN_INT is MIN_INT with the overflow flag set. | 8323 // -MIN_INT is MIN_INT with the overflow flag set. |
| 8307 unsafe_bailout_->Branch(overflow); | 8324 unsafe_bailout_->Branch(overflow); |
| 8308 } else { | 8325 } else { |
| 8309 // MIN_INT and 0 both have bad negations. They both have 31 zeros. | 8326 // MIN_INT and 0 both have bad negations. They both have 31 zeros. |
| 8310 __ test(value.reg(), Immediate(0x7FFFFFFF)); | 8327 __ test(value.reg(), Immediate(0x7FFFFFFF)); |
| 8311 unsafe_bailout_->Branch(zero); | 8328 unsafe_bailout_->Branch(zero); |
| 8312 } | 8329 } |
| 8313 break; | 8330 break; |
| 8314 } | 8331 } |
| 8315 case Token::BIT_NOT: { | 8332 case Token::BIT_NOT: { |
| 8316 __ not_(value.reg()); | 8333 __ not_(value.reg()); |
| 8334 frame_->Push(&value); |
| 8317 break; | 8335 break; |
| 8318 } | 8336 } |
| 8319 case Token::ADD: { | 8337 case Token::ADD: { |
| 8320 // Unary plus has no effect on int32 values. | 8338 // Unary plus has no effect on int32 values. |
| 8339 frame_->Push(&value); |
| 8321 break; | 8340 break; |
| 8322 } | 8341 } |
| 8323 default: | 8342 default: |
| 8324 UNREACHABLE(); | 8343 UNREACHABLE(); |
| 8325 break; | 8344 break; |
| 8326 } | 8345 } |
| 8327 frame_->Push(&value); | |
| 8328 } else { | 8346 } else { |
| 8329 Load(node->expression()); | 8347 Load(node->expression()); |
| 8330 bool can_overwrite = node->expression()->ResultOverwriteAllowed(); | 8348 bool can_overwrite = node->expression()->ResultOverwriteAllowed(); |
| 8331 UnaryOverwriteMode overwrite = | 8349 UnaryOverwriteMode overwrite = |
| 8332 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 8350 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| 8333 bool no_negative_zero = node->expression()->no_negative_zero(); | 8351 bool no_negative_zero = node->expression()->no_negative_zero(); |
| 8334 switch (op) { | 8352 switch (op) { |
| 8335 case Token::NOT: | 8353 case Token::NOT: |
| 8336 case Token::DELETE: | 8354 case Token::DELETE: |
| 8337 case Token::TYPEOF: | 8355 case Token::TYPEOF: |
| (...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9455 | 9473 |
| 9456 if (!dst_.is(eax)) __ mov(dst_, eax); | 9474 if (!dst_.is(eax)) __ mov(dst_, eax); |
| 9457 } | 9475 } |
| 9458 | 9476 |
| 9459 | 9477 |
| 9460 class DeferredReferenceSetKeyedValue: public DeferredCode { | 9478 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 9461 public: | 9479 public: |
| 9462 DeferredReferenceSetKeyedValue(Register value, | 9480 DeferredReferenceSetKeyedValue(Register value, |
| 9463 Register key, | 9481 Register key, |
| 9464 Register receiver, | 9482 Register receiver, |
| 9465 Register scratch) | 9483 Register scratch, |
| 9484 StrictModeFlag strict_mode) |
| 9466 : value_(value), | 9485 : value_(value), |
| 9467 key_(key), | 9486 key_(key), |
| 9468 receiver_(receiver), | 9487 receiver_(receiver), |
| 9469 scratch_(scratch) { | 9488 scratch_(scratch), |
| 9489 strict_mode_(strict_mode) { |
| 9470 set_comment("[ DeferredReferenceSetKeyedValue"); | 9490 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 9471 } | 9491 } |
| 9472 | 9492 |
| 9473 virtual void Generate(); | 9493 virtual void Generate(); |
| 9474 | 9494 |
| 9475 Label* patch_site() { return &patch_site_; } | 9495 Label* patch_site() { return &patch_site_; } |
| 9476 | 9496 |
| 9477 private: | 9497 private: |
| 9478 Register value_; | 9498 Register value_; |
| 9479 Register key_; | 9499 Register key_; |
| 9480 Register receiver_; | 9500 Register receiver_; |
| 9481 Register scratch_; | 9501 Register scratch_; |
| 9482 Label patch_site_; | 9502 Label patch_site_; |
| 9503 StrictModeFlag strict_mode_; |
| 9483 }; | 9504 }; |
| 9484 | 9505 |
| 9485 | 9506 |
| 9486 void DeferredReferenceSetKeyedValue::Generate() { | 9507 void DeferredReferenceSetKeyedValue::Generate() { |
| 9487 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), 1); | 9508 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), 1); |
| 9488 // Move value_ to eax, key_ to ecx, and receiver_ to edx. | 9509 // Move value_ to eax, key_ to ecx, and receiver_ to edx. |
| 9489 Register old_value = value_; | 9510 Register old_value = value_; |
| 9490 | 9511 |
| 9491 // First, move value to eax. | 9512 // First, move value to eax. |
| 9492 if (!value_.is(eax)) { | 9513 if (!value_.is(eax)) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9532 } | 9553 } |
| 9533 } else { // Key is not in edx or ecx. | 9554 } else { // Key is not in edx or ecx. |
| 9534 if (!receiver_.is(edx)) { | 9555 if (!receiver_.is(edx)) { |
| 9535 __ mov(edx, receiver_); | 9556 __ mov(edx, receiver_); |
| 9536 } | 9557 } |
| 9537 __ mov(ecx, key_); | 9558 __ mov(ecx, key_); |
| 9538 } | 9559 } |
| 9539 | 9560 |
| 9540 // Call the IC stub. | 9561 // Call the IC stub. |
| 9541 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 9562 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 9542 Builtins::KeyedStoreIC_Initialize)); | 9563 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict |
| 9564 : Builtins::KeyedStoreIC_Initialize)); |
| 9543 __ call(ic, RelocInfo::CODE_TARGET); | 9565 __ call(ic, RelocInfo::CODE_TARGET); |
| 9544 // The delta from the start of the map-compare instruction to the | 9566 // The delta from the start of the map-compare instruction to the |
| 9545 // test instruction. We use masm_-> directly here instead of the | 9567 // test instruction. We use masm_-> directly here instead of the |
| 9546 // __ macro because the macro sometimes uses macro expansion to turn | 9568 // __ macro because the macro sometimes uses macro expansion to turn |
| 9547 // into something that can't return a value. This is encountered | 9569 // into something that can't return a value. This is encountered |
| 9548 // when doing generated code coverage tests. | 9570 // when doing generated code coverage tests. |
| 9549 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 9571 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
| 9550 // Here we use masm_-> instead of the __ macro because this is the | 9572 // Here we use masm_-> instead of the __ macro because this is the |
| 9551 // instruction that gets patched and coverage code gets in the way. | 9573 // instruction that gets patched and coverage code gets in the way. |
| 9552 masm_->test(eax, Immediate(-delta_to_patch_site)); | 9574 masm_->test(eax, Immediate(-delta_to_patch_site)); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9674 } | 9696 } |
| 9675 | 9697 |
| 9676 | 9698 |
| 9677 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { | 9699 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
| 9678 #ifdef DEBUG | 9700 #ifdef DEBUG |
| 9679 int expected_height = frame()->height() - (is_contextual ? 1 : 2); | 9701 int expected_height = frame()->height() - (is_contextual ? 1 : 2); |
| 9680 #endif | 9702 #endif |
| 9681 | 9703 |
| 9682 Result result; | 9704 Result result; |
| 9683 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { | 9705 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
| 9684 result = frame()->CallStoreIC(name, is_contextual); | 9706 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 9685 // A test eax instruction following the call signals that the inobject | 9707 // A test eax instruction following the call signals that the inobject |
| 9686 // property case was inlined. Ensure that there is not a test eax | 9708 // property case was inlined. Ensure that there is not a test eax |
| 9687 // instruction here. | 9709 // instruction here. |
| 9688 __ nop(); | 9710 __ nop(); |
| 9689 } else { | 9711 } else { |
| 9690 // Inline the in-object property case. | 9712 // Inline the in-object property case. |
| 9691 JumpTarget slow, done; | 9713 JumpTarget slow, done; |
| 9692 Label patch_site; | 9714 Label patch_site; |
| 9693 | 9715 |
| 9694 // Get the value and receiver from the stack. | 9716 // Get the value and receiver from the stack. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9758 } | 9780 } |
| 9759 __ bind(&skip_write_barrier); | 9781 __ bind(&skip_write_barrier); |
| 9760 value.Unuse(); | 9782 value.Unuse(); |
| 9761 scratch.Unuse(); | 9783 scratch.Unuse(); |
| 9762 receiver.Unuse(); | 9784 receiver.Unuse(); |
| 9763 done.Jump(&result); | 9785 done.Jump(&result); |
| 9764 | 9786 |
| 9765 slow.Bind(&value, &receiver); | 9787 slow.Bind(&value, &receiver); |
| 9766 frame()->Push(&receiver); | 9788 frame()->Push(&receiver); |
| 9767 frame()->Push(&value); | 9789 frame()->Push(&value); |
| 9768 result = frame()->CallStoreIC(name, is_contextual); | 9790 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 9769 // Encode the offset to the map check instruction and the offset | 9791 // Encode the offset to the map check instruction and the offset |
| 9770 // to the write barrier store address computation in a test eax | 9792 // to the write barrier store address computation in a test eax |
| 9771 // instruction. | 9793 // instruction. |
| 9772 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); | 9794 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); |
| 9773 __ test(eax, | 9795 __ test(eax, |
| 9774 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); | 9796 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); |
| 9775 done.Bind(&result); | 9797 done.Bind(&result); |
| 9776 } | 9798 } |
| 9777 | 9799 |
| 9778 ASSERT_EQ(expected_height, frame()->height()); | 9800 ASSERT_EQ(expected_height, frame()->height()); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9896 | 9918 |
| 9897 // Make sure that value, key and receiver are in registers. | 9919 // Make sure that value, key and receiver are in registers. |
| 9898 result.ToRegister(); | 9920 result.ToRegister(); |
| 9899 key.ToRegister(); | 9921 key.ToRegister(); |
| 9900 receiver.ToRegister(); | 9922 receiver.ToRegister(); |
| 9901 | 9923 |
| 9902 DeferredReferenceSetKeyedValue* deferred = | 9924 DeferredReferenceSetKeyedValue* deferred = |
| 9903 new DeferredReferenceSetKeyedValue(result.reg(), | 9925 new DeferredReferenceSetKeyedValue(result.reg(), |
| 9904 key.reg(), | 9926 key.reg(), |
| 9905 receiver.reg(), | 9927 receiver.reg(), |
| 9906 tmp.reg()); | 9928 tmp.reg(), |
| 9929 strict_mode_flag()); |
| 9907 | 9930 |
| 9908 // Check that the receiver is not a smi. | 9931 // Check that the receiver is not a smi. |
| 9909 __ test(receiver.reg(), Immediate(kSmiTagMask)); | 9932 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
| 9910 deferred->Branch(zero); | 9933 deferred->Branch(zero); |
| 9911 | 9934 |
| 9912 // Check that the key is a smi. | 9935 // Check that the key is a smi. |
| 9913 if (!key.is_smi()) { | 9936 if (!key.is_smi()) { |
| 9914 __ test(key.reg(), Immediate(kSmiTagMask)); | 9937 __ test(key.reg(), Immediate(kSmiTagMask)); |
| 9915 deferred->Branch(not_zero); | 9938 deferred->Branch(not_zero); |
| 9916 } else { | 9939 } else { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9951 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), | 9974 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), |
| 9952 Immediate(FACTORY->fixed_array_map())); | 9975 Immediate(FACTORY->fixed_array_map())); |
| 9953 deferred->Branch(not_equal); | 9976 deferred->Branch(not_equal); |
| 9954 | 9977 |
| 9955 // Store the value. | 9978 // Store the value. |
| 9956 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg()); | 9979 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg()); |
| 9957 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1); | 9980 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1); |
| 9958 | 9981 |
| 9959 deferred->BindExit(); | 9982 deferred->BindExit(); |
| 9960 } else { | 9983 } else { |
| 9961 result = frame()->CallKeyedStoreIC(); | 9984 result = frame()->CallKeyedStoreIC(strict_mode_flag()); |
| 9962 // Make sure that we do not have a test instruction after the | 9985 // Make sure that we do not have a test instruction after the |
| 9963 // call. A test instruction after the call is used to | 9986 // call. A test instruction after the call is used to |
| 9964 // indicate that we have generated an inline version of the | 9987 // indicate that we have generated an inline version of the |
| 9965 // keyed store. | 9988 // keyed store. |
| 9966 __ nop(); | 9989 __ nop(); |
| 9967 } | 9990 } |
| 9968 ASSERT(frame()->height() == original_height - 3); | 9991 ASSERT(frame()->height() == original_height - 3); |
| 9969 return result; | 9992 return result; |
| 9970 } | 9993 } |
| 9971 | 9994 |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10331 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); | 10354 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); |
| 10332 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); | 10355 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); |
| 10333 return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress()); | 10356 return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress()); |
| 10334 } | 10357 } |
| 10335 | 10358 |
| 10336 #undef __ | 10359 #undef __ |
| 10337 | 10360 |
| 10338 } } // namespace v8::internal | 10361 } } // namespace v8::internal |
| 10339 | 10362 |
| 10340 #endif // V8_TARGET_ARCH_IA32 | 10363 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |