Revision: 6652
Author: [email protected]
Date: Fri Feb 4 10:15:49 2011
Log: Pass strict mode to eval.
Code review feedback.
Code Review URL: http://codereview.chromium.org/6286043/
http://code.google.com/p/v8/source/detail?r=6652
Added:
/branches/bleeding_edge/test/mjsunit/strict-mode-eval.js
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.h
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/codegen-inl.h
/branches/bleeding_edge/src/compilation-cache.cc
/branches/bleeding_edge/src/compilation-cache.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/compiler.h
/branches/bleeding_edge/src/full-codegen.h
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/parser.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/v8globals.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.h
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/strict-mode-eval.js Fri Feb 4
10:15:49 2011
@@ -0,0 +1,82 @@
+// 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:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"use strict";
+
+var code1 = "function f(eval) {}";
+var code2 = "function f(a, a) {}";
+var code3 = "var x = '\\020;'";
+var code4 = "function arguments() {}";
+
+// Verify the code compiles just fine in non-strict mode
+// (using aliased eval to force non-strict mode)
+var eval_alias = eval;
+
+eval_alias(code1);
+eval_alias(code2);
+eval_alias(code3);
+eval_alias(code4);
+
+function strict1() {
+ try {
+ eval(code1);
+ assertUnreachable("did not throw exception");
+ } catch (e) {
+ assertInstanceof(e, SyntaxError);
+ }
+
+ function strict2() {
+ try {
+ eval(code2);
+ assertUnreachable("did not throw exception");
+ } catch (e) {
+ assertInstanceof(e, SyntaxError);
+ }
+
+ function strict3() {
+ try {
+ eval(code3);
+ assertUnreachable("did not throw exception");
+ } catch (e) {
+ assertInstanceof(e, SyntaxError);
+ }
+
+ function strict4() {
+ try {
+ eval(code4);
+ assertUnreachable("did not throw exception");
+ } catch (e) {
+ assertInstanceof(e, SyntaxError);
+ }
+ }
+ strict4();
+ }
+ strict3();
+ }
+ strict2();
+}
+strict1();
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Feb 4 02:52:19 2011
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Feb 4 10:15:49 2011
@@ -4177,7 +4177,10 @@
__ ldr(r1, frame_->Receiver());
frame_->EmitPush(r1);
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3);
+ // Push the strict mode flag.
+ frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+
+ frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);
done.Jump();
slow.Bind();
@@ -4197,8 +4200,11 @@
__ ldr(r1, frame_->Receiver());
frame_->EmitPush(r1);
+ // Push the strict mode flag.
+ frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+
// Resolve the call.
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// If we generated fast-case code bind the jump-target where fast
// and slow case merge.
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h Tue Dec 7 03:31:57 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h Fri Feb 4 10:15:49 2011
@@ -287,6 +287,7 @@
// Accessors
inline bool is_eval();
inline Scope* scope();
+ inline StrictModeFlag strict_mode_flag();
// Generating deferred code.
void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Feb 4 02:52:19
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Feb 4 10:15:49
2011
@@ -1926,7 +1926,10 @@
__ ldr(r1,
MemOperand(fp, (2 + scope()->num_parameters()) *
kPointerSize));
__ push(r1);
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ // Push the strict mode flag.
+ __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+ __ push(r1);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// The runtime call returns a pair of values in r0 (function) and
// r1 (receiver). Touch up the stack with the right values.
=======================================
--- /branches/bleeding_edge/src/codegen-inl.h Tue Dec 7 03:01:02 2010
+++ /branches/bleeding_edge/src/codegen-inl.h Fri Feb 4 10:15:49 2011
@@ -54,6 +54,10 @@
bool CodeGenerator::is_eval() { return info_->is_eval(); }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
+
+StrictModeFlag CodeGenerator::strict_mode_flag() {
+ return info_->function()->strict_mode() ? kStrictMode : kNonStrictMode;
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/compilation-cache.cc Tue Dec 7 03:31:57
2010
+++ /branches/bleeding_edge/src/compilation-cache.cc Fri Feb 4 10:15:49
2011
@@ -136,7 +136,8 @@
: CompilationSubCache(generations) { }
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
- Handle<Context> context);
+ Handle<Context> context,
+ StrictModeFlag strict_mode);
void Put(Handle<String> source,
Handle<Context> context,
@@ -371,7 +372,9 @@
Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
- Handle<String> source, Handle<Context> context) {
+ Handle<String> source,
+ Handle<Context> context,
+ StrictModeFlag strict_mode) {
// Make sure not to leak the table into the surrounding handle
// scope. Otherwise, we risk keeping old tables around even after
// having cleared the cache.
@@ -380,7 +383,7 @@
{ HandleScope scope;
for (generation = 0; generation < generations(); generation++) {
Handle<CompilationCacheTable> table = GetTable(generation);
- result = table->LookupEval(*source, *context);
+ result = table->LookupEval(*source, *context, strict_mode);
if (result->IsSharedFunctionInfo()) {
break;
}
@@ -503,18 +506,20 @@
}
-Handle<SharedFunctionInfo> CompilationCache::LookupEval(Handle<String>
source,
- Handle<Context>
context,
- bool is_global) {
+Handle<SharedFunctionInfo> CompilationCache::LookupEval(
+ Handle<String> source,
+ Handle<Context> context,
+ bool is_global,
+ StrictModeFlag strict_mode) {
if (!IsEnabled()) {
return Handle<SharedFunctionInfo>::null();
}
Handle<SharedFunctionInfo> result;
if (is_global) {
- result = eval_global.Lookup(source, context);
+ result = eval_global.Lookup(source, context, strict_mode);
} else {
- result = eval_contextual.Lookup(source, context);
+ result = eval_contextual.Lookup(source, context, strict_mode);
}
return result;
}
=======================================
--- /branches/bleeding_edge/src/compilation-cache.h Tue Dec 7 03:31:57 2010
+++ /branches/bleeding_edge/src/compilation-cache.h Fri Feb 4 10:15:49 2011
@@ -51,7 +51,8 @@
// contain a script for the given source string.
static Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
Handle<Context> context,
- bool is_global);
+ bool is_global,
+ StrictModeFlag strict_mode);
// Returns the regexp data associated with the given regexp if it
// is in cache, otherwise an empty handle.
=======================================
--- /branches/bleeding_edge/src/compiler.cc Wed Jan 19 05:55:56 2011
+++ /branches/bleeding_edge/src/compiler.cc Fri Feb 4 10:15:49 2011
@@ -548,7 +548,8 @@
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
- bool is_global) {
+ bool is_global,
+ StrictModeFlag
strict_mode) {
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
Counters::total_compile_size.Increment(source_length);
@@ -559,7 +560,10 @@
// Do a lookup in the compilation cache; if the entry is not there,
invoke
// the compiler and add the result to the cache.
Handle<SharedFunctionInfo> result;
- result = CompilationCache::LookupEval(source, context, is_global);
+ result = CompilationCache::LookupEval(source,
+ context,
+ is_global,
+ strict_mode);
if (result.is_null()) {
// Create a script object describing the script to be compiled.
@@ -567,9 +571,14 @@
CompilationInfo info(script);
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
+ if (strict_mode == kStrictMode) info.MarkAsStrict();
info.SetCallingContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
+ // If caller is strict mode, the result must be strict as well,
+ // but not the other way around. Consider:
+ // eval("'use strict'; ...");
+ ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
CompilationCache::PutEval(source, context, is_global, result);
}
}
@@ -762,6 +771,7 @@
*lit->this_property_assignments());
function_info->set_try_full_codegen(lit->try_full_codegen());
function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
+ function_info->set_strict_mode(lit->strict_mode());
}
=======================================
--- /branches/bleeding_edge/src/compiler.h Tue Jan 18 05:43:48 2011
+++ /branches/bleeding_edge/src/compiler.h Fri Feb 4 10:15:49 2011
@@ -49,6 +49,7 @@
bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
+ bool is_strict() const { return (flags_ & IsStrict::mask()) != 0; }
bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
@@ -69,6 +70,13 @@
ASSERT(!is_lazy());
flags_ |= IsGlobal::encode(true);
}
+ void MarkAsStrict() {
+ ASSERT(!is_lazy());
+ flags_ |= IsStrict::encode(true);
+ }
+ StrictModeFlag StrictMode() {
+ return is_strict() ? kStrictMode : kNonStrictMode;
+ }
void MarkAsInLoop() {
ASSERT(is_lazy());
flags_ |= IsInLoop::encode(true);
@@ -162,6 +170,8 @@
class IsGlobal: public BitField<bool, 2, 1> {};
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 3, 1> {};
+ // Strict mode - used in eager compilation.
+ class IsStrict: public BitField<bool, 4, 1> {};
unsigned flags_;
@@ -230,7 +240,8 @@
// Compile a String source within a context for Eval.
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
Handle<Context> context,
- bool is_global);
+ bool is_global,
+ StrictModeFlag
strict_mode);
// Compile from function info (used for lazy compilation). Returns true
on
// success and false if the compilation resulted in a stack overflow.
=======================================
--- /branches/bleeding_edge/src/full-codegen.h Wed Dec 15 08:14:29 2010
+++ /branches/bleeding_edge/src/full-codegen.h Fri Feb 4 10:15:49 2011
@@ -531,6 +531,9 @@
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
+ StrictModeFlag strict_mode_flag() {
+ return function()->strict_mode() ? kStrictMode : kNonStrictMode;
+ }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return info_->scope(); }
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Feb 2 04:54:58
2011
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 4 10:15:49
2011
@@ -6102,9 +6102,12 @@
}
frame_->PushParameterAt(-1);
+ // Push the strict mode flag.
+ frame_->Push(Smi::FromInt(strict_mode_flag()));
+
// Resolve the call.
result =
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup,
3);
+ frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup,
4);
done.Jump(&result);
slow.Bind();
@@ -6121,8 +6124,11 @@
}
frame_->PushParameterAt(-1);
+ // Push the strict mode flag.
+ frame_->Push(Smi::FromInt(strict_mode_flag()));
+
// Resolve the call.
- result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// If we generated fast-case code bind the jump-target where fast
// and slow case merge.
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Tue Dec 7 03:31:57 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Feb 4 10:15:49 2011
@@ -365,6 +365,7 @@
// Accessors
inline bool is_eval();
inline Scope* scope();
+ inline StrictModeFlag strict_mode_flag();
// Generating deferred code.
void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 4
04:06:41 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 4
10:15:49 2011
@@ -2292,7 +2292,9 @@
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(ebp, (2 + scope()->num_parameters()) *
kPointerSize));
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ // Push the strict mode flag.
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// The runtime call returns a pair of values in eax (function) and
// edx (receiver). Touch up the stack with the right values.
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Feb 3 02:07:22 2011
+++ /branches/bleeding_edge/src/objects-inl.h Fri Feb 4 10:15:49 2011
@@ -2991,6 +2991,18 @@
code()->set_optimizable(false);
}
}
+
+
+bool SharedFunctionInfo::strict_mode() {
+ return BooleanBit::get(compiler_hints(), kStrictModeFunction);
+}
+
+
+void SharedFunctionInfo::set_strict_mode(bool value) {
+ set_compiler_hints(BooleanBit::set(compiler_hints(),
+ kStrictModeFunction,
+ value));
+}
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Feb 4 06:09:03 2011
+++ /branches/bleeding_edge/src/objects.cc Fri Feb 4 10:15:49 2011
@@ -7998,20 +7998,28 @@
// StringSharedKeys are used as keys in the eval cache.
class StringSharedKey : public HashTableKey {
public:
- StringSharedKey(String* source, SharedFunctionInfo* shared)
- : source_(source), shared_(shared) { }
+ StringSharedKey(String* source,
+ SharedFunctionInfo* shared,
+ StrictModeFlag strict_mode)
+ : source_(source),
+ shared_(shared),
+ strict_mode_(strict_mode) { }
bool IsMatch(Object* other) {
if (!other->IsFixedArray()) return false;
FixedArray* pair = FixedArray::cast(other);
SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
if (shared != shared_) return false;
+ StrictModeFlag strict_mode = static_cast<StrictModeFlag>(
+ Smi::cast(pair->get(2))->value());
+ if (strict_mode != strict_mode_) return false;
String* source = String::cast(pair->get(1));
return source->Equals(source_);
}
static uint32_t StringSharedHashHelper(String* source,
- SharedFunctionInfo* shared) {
+ SharedFunctionInfo* shared,
+ StrictModeFlag strict_mode) {
uint32_t hash = source->Hash();
if (shared->HasSourceCode()) {
// Instead of using the SharedFunctionInfo pointer in the hash
@@ -8021,36 +8029,41 @@
// collection.
Script* script = Script::cast(shared->script());
hash ^= String::cast(script->source())->Hash();
+ if (strict_mode == kStrictMode) hash ^= 0x8000;
hash += shared->start_position();
}
return hash;
}
uint32_t Hash() {
- return StringSharedHashHelper(source_, shared_);
+ return StringSharedHashHelper(source_, shared_, strict_mode_);
}
uint32_t HashForObject(Object* obj) {
FixedArray* pair = FixedArray::cast(obj);
SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
String* source = String::cast(pair->get(1));
- return StringSharedHashHelper(source, shared);
+ StrictModeFlag strict_mode = static_cast<StrictModeFlag>(
+ Smi::cast(pair->get(2))->value());
+ return StringSharedHashHelper(source, shared, strict_mode);
}
MUST_USE_RESULT MaybeObject* AsObject() {
Object* obj;
- { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2);
+ { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* pair = FixedArray::cast(obj);
pair->set(0, shared_);
pair->set(1, source_);
+ pair->set(2, Smi::FromInt(strict_mode_));
return pair;
}
private:
String* source_;
SharedFunctionInfo* shared_;
+ StrictModeFlag strict_mode_;
};
@@ -9009,8 +9022,10 @@
}
-Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
- StringSharedKey key(src, context->closure()->shared());
+Object* CompilationCacheTable::LookupEval(String* src,
+ Context* context,
+ StrictModeFlag strict_mode) {
+ StringSharedKey key(src, context->closure()->shared(), strict_mode);
int entry = FindEntry(&key);
if (entry == kNotFound) return Heap::undefined_value();
return get(EntryToIndex(entry) + 1);
@@ -9045,8 +9060,10 @@
MaybeObject* CompilationCacheTable::PutEval(String* src,
Context* context,
- Object* value) {
- StringSharedKey key(src, context->closure()->shared());
+ SharedFunctionInfo* value) {
+ StringSharedKey key(src,
+ context->closure()->shared(),
+ value->strict_mode() ? kStrictMode : kNonStrictMode);
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Feb 3 02:07:22 2011
+++ /branches/bleeding_edge/src/objects.h Fri Feb 4 10:15:49 2011
@@ -4176,6 +4176,10 @@
inline bool optimization_disabled();
inline void set_optimization_disabled(bool value);
+ // Indicates whether the function is a strict mode function.
+ inline bool strict_mode();
+ inline void set_strict_mode(bool value);
+
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
@@ -4357,6 +4361,7 @@
static const int kCodeAgeShift = 4;
static const int kCodeAgeMask = 0x7;
static const int kOptimizationDisabled = 7;
+ static const int kStrictModeFunction = 8;
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};
@@ -4902,10 +4907,12 @@
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);
- Object* LookupEval(String* src, Context* context);
+ Object* LookupEval(String* src, Context* context, StrictModeFlag
strict_mode);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
MaybeObject* Put(String* src, Object* value);
- MaybeObject* PutEval(String* src, Context* context, Object* value);
+ MaybeObject* PutEval(String* src,
+ Context* context,
+ SharedFunctionInfo* value);
MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray*
value);
// Remove given value from cache.
=======================================
--- /branches/bleeding_edge/src/parser.cc Wed Feb 2 06:02:58 2011
+++ /branches/bleeding_edge/src/parser.cc Fri Feb 4 10:15:49 2011
@@ -616,7 +616,8 @@
FunctionLiteral* Parser::ParseProgram(Handle<String> source,
- bool in_global_context) {
+ bool in_global_context,
+ StrictModeFlag strict_mode) {
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::parse);
@@ -632,17 +633,18 @@
ExternalTwoByteStringUC16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source), 0, source->length());
scanner_.Initialize(&stream);
- return DoParseProgram(source, in_global_context, &zone_scope);
+ return DoParseProgram(source, in_global_context, strict_mode,
&zone_scope);
} else {
GenericStringUC16CharacterStream stream(source, 0, source->length());
scanner_.Initialize(&stream);
- return DoParseProgram(source, in_global_context, &zone_scope);
+ return DoParseProgram(source, in_global_context, strict_mode,
&zone_scope);
}
}
FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
bool in_global_context,
+ StrictModeFlag strict_mode,
ZoneScope* zone_scope) {
ASSERT(target_stack_ == NULL);
if (pre_data_ != NULL) pre_data_->Initialize();
@@ -662,6 +664,9 @@
LexicalScope lexical_scope(&this->top_scope_,
&this->with_nesting_level_,
scope);
TemporaryScope temp_scope(&this->temp_scope_);
+ if (strict_mode == kStrictMode) {
+ temp_scope.EnableStrictMode();
+ }
ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
bool ok = true;
int beg_loc = scanner().location().beg_pos;
@@ -747,6 +752,10 @@
scope);
TemporaryScope temp_scope(&this->temp_scope_);
+ if (info->strict_mode()) {
+ temp_scope.EnableStrictMode();
+ }
+
FunctionLiteralType type =
info->is_expression() ? EXPRESSION : DECLARATION;
bool ok = true;
@@ -5024,7 +5033,9 @@
ASSERT(Top::has_pending_exception());
} else {
Handle<String> source =
Handle<String>(String::cast(script->source()));
- result = parser.ParseProgram(source, info->is_global());
+ result = parser.ParseProgram(source,
+ info->is_global(),
+ info->StrictMode());
}
}
=======================================
--- /branches/bleeding_edge/src/parser.h Wed Jan 26 11:21:46 2011
+++ /branches/bleeding_edge/src/parser.h Fri Feb 4 10:15:49 2011
@@ -423,7 +423,8 @@
// Returns NULL if parsing failed.
FunctionLiteral* ParseProgram(Handle<String> source,
- bool in_global_context);
+ bool in_global_context,
+ StrictModeFlag strict_mode);
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
@@ -446,6 +447,7 @@
// Called by ParseProgram after setting up the scanner.
FunctionLiteral* DoParseProgram(Handle<String> source,
bool in_global_context,
+ StrictModeFlag strict_mode,
ZoneScope* zone_scope);
// Report syntax error
=======================================
--- /branches/bleeding_edge/src/runtime.cc Fri Feb 4 04:14:56 2011
+++ /branches/bleeding_edge/src/runtime.cc Fri Feb 4 10:15:49 2011
@@ -7674,7 +7674,8 @@
Handle<Context> context(Top::context()->global_context());
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
context,
- true);
+ true,
+
kNonStrictMode);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromSharedFunctionInfo(shared, context,
NOT_TENURED);
@@ -7683,13 +7684,15 @@
static ObjectPair CompileGlobalEval(Handle<String> source,
- Handle<Object> receiver) {
+ Handle<Object> receiver,
+ StrictModeFlag mode) {
// Deal with a normal eval call with a string argument. Compile it
// and return the compiled function bound in the local context.
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
source,
Handle<Context>(Top::context()),
- Top::context()->IsGlobalContext());
+ Top::context()->IsGlobalContext(),
+ mode);
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo(
shared,
@@ -7700,7 +7703,7 @@
static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) {
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
if (!args[0]->IsJSFunction()) {
return MakePair(Top::ThrowIllegalOperation(), NULL);
}
@@ -7764,12 +7767,16 @@
return MakePair(*callee, Top::context()->global()->global_receiver());
}
- return CompileGlobalEval(args.at<String>(1), args.at<Object>(2));
+ ASSERT(args[3]->IsSmi());
+ return CompileGlobalEval(args.at<String>(1),
+ args.at<Object>(2),
+ static_cast<StrictModeFlag>(
+ Smi::cast(args[3])->value()));
}
static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments
args) {
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
if (!args[0]->IsJSFunction()) {
return MakePair(Top::ThrowIllegalOperation(), NULL);
}
@@ -7784,7 +7791,11 @@
return MakePair(*callee, Top::context()->global()->global_receiver());
}
- return CompileGlobalEval(args.at<String>(1), args.at<Object>(2));
+ ASSERT(args[3]->IsSmi());
+ return CompileGlobalEval(args.at<String>(1),
+ args.at<Object>(2),
+ static_cast<StrictModeFlag>(
+ Smi::cast(args[3])->value()));
}
@@ -9921,10 +9932,14 @@
Handle<String> function_source =
Factory::NewStringFromAscii(Vector<const char>(source_str,
source_str_length));
+
+ // Currently, the eval code will be executed in non-strict mode,
+ // even in the strict code context.
Handle<SharedFunctionInfo> shared =
Compiler::CompileEval(function_source,
context,
- context->IsGlobalContext());
+ context->IsGlobalContext(),
+ kNonStrictMode);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Factory::NewFunctionFromSharedFunctionInfo(shared, context);
@@ -10006,10 +10021,10 @@
}
// Compile the source to be evaluated.
+ // Currently, the eval code will be executed in non-strict mode,
+ // even in the strict code context.
Handle<SharedFunctionInfo> shared =
- Compiler::CompileEval(source,
- context,
- is_global);
+ Compiler::CompileEval(source, context, is_global, kNonStrictMode);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
=======================================
--- /branches/bleeding_edge/src/runtime.h Wed Feb 2 05:31:52 2011
+++ /branches/bleeding_edge/src/runtime.h Fri Feb 4 10:15:49 2011
@@ -237,8 +237,8 @@
\
/* Eval */ \
F(GlobalReceiver, 1, 1) \
- F(ResolvePossiblyDirectEval, 3, 2) \
- F(ResolvePossiblyDirectEvalNoLookup, 3, 2) \
+ F(ResolvePossiblyDirectEval, 4, 2) \
+ F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \
\
F(SetProperty, -1 /* 3 or 4 */, 1) \
F(DefineOrRedefineDataProperty, 4, 1) \
=======================================
--- /branches/bleeding_edge/src/v8globals.h Fri Jan 14 05:16:48 2011
+++ /branches/bleeding_edge/src/v8globals.h Fri Feb 4 10:15:49 2011
@@ -469,6 +469,12 @@
ARMv7 = 2, // ARM
SAHF = 0}; // x86
+// The Strict Mode (ECMA-262 5th edition, 4.2.2).
+enum StrictModeFlag {
+ kNonStrictMode,
+ kStrictMode
+};
+
} } // namespace v8::internal
#endif // V8_V8GLOBALS_H_
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Feb 2 04:54:58 2011
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Feb 4 10:15:49 2011
@@ -5402,9 +5402,12 @@
}
frame_->PushParameterAt(-1);
+ // Push the strict mode flag.
+ frame_->Push(Smi::FromInt(strict_mode_flag()));
+
// Resolve the call.
result =
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup,
3);
+ frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup,
4);
done.Jump(&result);
slow.Bind();
@@ -5421,8 +5424,11 @@
}
frame_->PushParameterAt(-1);
+ // Push the strict mode flag.
+ frame_->Push(Smi::FromInt(strict_mode_flag()));
+
// Resolve the call.
- result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// If we generated fast-case code bind the jump-target where fast
// and slow case merge.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Tue Dec 7 03:31:57 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Fri Feb 4 10:15:49 2011
@@ -357,6 +357,7 @@
// Accessors
inline bool is_eval();
inline Scope* scope();
+ inline StrictModeFlag strict_mode_flag();
// Generating deferred code.
void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Feb 3 07:36:44
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Feb 4 10:15:49
2011
@@ -1924,7 +1924,9 @@
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) *
kPointerSize));
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ // Push the strict mode flag.
+ __ Push(Smi::FromInt(strict_mode_flag()));
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// The runtime call returns a pair of values in rax (function) and
// rdx (receiver). Touch up the stack with the right values.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev