| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 7031)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -2748,7 +2748,8 @@
|
| frame_->EmitPush(rsi); // The context is the first argument.
|
| frame_->EmitPush(kScratchRegister);
|
| frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
|
| - Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
|
| + frame_->EmitPush(Smi::FromInt(strict_mode_flag()));
|
| + Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
|
| // Return value is ignored.
|
| }
|
|
|
| @@ -4606,7 +4607,8 @@
|
| // by initialization.
|
| value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
|
| } else {
|
| - value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
|
| + frame_->Push(Smi::FromInt(strict_mode_flag()));
|
| + value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
|
| }
|
| // Storing a variable must keep the (new) value on the expression
|
| // stack. This is necessary for compiling chained assignment
|
| @@ -4895,7 +4897,8 @@
|
| Load(property->value());
|
| if (property->emit_store()) {
|
| Result ignored =
|
| - frame_->CallStoreIC(Handle<String>::cast(key), false);
|
| + frame_->CallStoreIC(Handle<String>::cast(key), false,
|
| + strict_mode_flag());
|
| // A test rax instruction following the store IC call would
|
| // indicate the presence of an inlined version of the
|
| // store. Add a nop to indicate that there is no such
|
| @@ -4914,8 +4917,9 @@
|
| Load(property->key());
|
| Load(property->value());
|
| if (property->emit_store()) {
|
| + frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes
|
| // Ignore the result.
|
| - Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
|
| + Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
|
| } else {
|
| frame_->Drop(3);
|
| }
|
| @@ -7030,7 +7034,8 @@
|
| void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 1);
|
| Load(args->at(0));
|
| - TranscendentalCacheStub stub(TranscendentalCache::SIN);
|
| + TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
| + TranscendentalCacheStub::TAGGED);
|
| Result result = frame_->CallStub(&stub, 1);
|
| frame_->Push(&result);
|
| }
|
| @@ -7039,7 +7044,8 @@
|
| void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 1);
|
| Load(args->at(0));
|
| - TranscendentalCacheStub stub(TranscendentalCache::COS);
|
| + TranscendentalCacheStub stub(TranscendentalCache::COS,
|
| + TranscendentalCacheStub::TAGGED);
|
| Result result = frame_->CallStub(&stub, 1);
|
| frame_->Push(&result);
|
| }
|
| @@ -7048,7 +7054,8 @@
|
| void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 1);
|
| Load(args->at(0));
|
| - TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
| + TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
| + TranscendentalCacheStub::TAGGED);
|
| Result result = frame_->CallStub(&stub, 1);
|
| frame_->Push(&result);
|
| }
|
| @@ -7230,21 +7237,25 @@
|
| if (property != NULL) {
|
| Load(property->obj());
|
| Load(property->key());
|
| - Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
|
| + frame_->Push(Smi::FromInt(strict_mode_flag()));
|
| + Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
|
| frame_->Push(&answer);
|
| return;
|
| }
|
|
|
| Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
|
| if (variable != NULL) {
|
| + // Delete of an unqualified identifier is disallowed in strict mode
|
| + // but "delete this" is.
|
| + ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
|
| Slot* slot = variable->AsSlot();
|
| if (variable->is_global()) {
|
| LoadGlobal();
|
| frame_->Push(variable->name());
|
| + frame_->Push(Smi::FromInt(kNonStrictMode));
|
| Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
|
| - CALL_FUNCTION, 2);
|
| + CALL_FUNCTION, 3);
|
| frame_->Push(&answer);
|
| - return;
|
|
|
| } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
| // Call the runtime to delete from the context holding the named
|
| @@ -7255,13 +7266,11 @@
|
| frame_->EmitPush(variable->name());
|
| Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
|
| frame_->Push(&answer);
|
| - return;
|
| + } else {
|
| + // Default: Result of deleting non-global, not dynamically
|
| + // introduced variables is false.
|
| + frame_->Push(FACTORY->false_value());
|
| }
|
| -
|
| - // Default: Result of deleting non-global, not dynamically
|
| - // introduced variables is false.
|
| - frame_->Push(FACTORY->false_value());
|
| -
|
| } else {
|
| // Default: Result of deleting expressions is true.
|
| Load(node->expression()); // may have side-effects
|
| @@ -8072,8 +8081,12 @@
|
| public:
|
| DeferredReferenceSetKeyedValue(Register value,
|
| Register key,
|
| - Register receiver)
|
| - : value_(value), key_(key), receiver_(receiver) {
|
| + Register receiver,
|
| + StrictModeFlag strict_mode)
|
| + : value_(value),
|
| + key_(key),
|
| + receiver_(receiver),
|
| + strict_mode_(strict_mode) {
|
| set_comment("[ DeferredReferenceSetKeyedValue");
|
| }
|
|
|
| @@ -8086,6 +8099,7 @@
|
| Register key_;
|
| Register receiver_;
|
| Label patch_site_;
|
| + StrictModeFlag strict_mode_;
|
| };
|
|
|
|
|
| @@ -8138,7 +8152,8 @@
|
|
|
| // Call the IC stub.
|
| Handle<Code> ic(Isolate::Current()->builtins()->builtin(
|
| - Builtins::KeyedStoreIC_Initialize));
|
| + (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
|
| + : Builtins::KeyedStoreIC_Initialize));
|
| __ Call(ic, RelocInfo::CODE_TARGET);
|
| // The delta from the start of the map-compare instructions (initial movq)
|
| // to the test instruction. We use masm_-> directly here instead of the
|
| @@ -8238,7 +8253,7 @@
|
|
|
| Result result;
|
| if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
|
| - result = frame()->CallStoreIC(name, is_contextual);
|
| + result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag());
|
| // A test rax instruction following the call signals that the inobject
|
| // property case was inlined. Ensure that there is not a test rax
|
| // instruction here.
|
| @@ -8338,7 +8353,7 @@
|
| slow.Bind(&value, &receiver);
|
| frame()->Push(&receiver);
|
| frame()->Push(&value);
|
| - result = frame()->CallStoreIC(name, is_contextual);
|
| + result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag());
|
| // Encode the offset to the map check instruction and the offset
|
| // to the write barrier store address computation in a test rax
|
| // instruction.
|
| @@ -8479,7 +8494,8 @@
|
| DeferredReferenceSetKeyedValue* deferred =
|
| new DeferredReferenceSetKeyedValue(result.reg(),
|
| key.reg(),
|
| - receiver.reg());
|
| + receiver.reg(),
|
| + strict_mode_flag());
|
|
|
| // Check that the receiver is not a smi.
|
| __ JumpIfSmi(receiver.reg(), deferred->entry_label());
|
| @@ -8541,7 +8557,7 @@
|
|
|
| deferred->BindExit();
|
| } else {
|
| - result = frame()->CallKeyedStoreIC();
|
| + result = frame()->CallKeyedStoreIC(strict_mode_flag());
|
| // Make sure that we do not have a test instruction after the
|
| // call. A test instruction after the call is used to
|
| // indicate that we have generated an inline version of the
|
|
|