From 87233c49c86fa47d4bcf2f002edda566e0532951 Mon Sep 17 00:00:00 2001 From: "mmaly@chromium.org" Date: Fri, 4 Feb 2011 18:15:49 +0000 Subject: [PATCH] Pass strict mode to eval. Code review feedback. Code Review URL: http://codereview.chromium.org/6286043/ git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6652 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 10 ++++- src/arm/codegen-arm.h | 1 + src/arm/full-codegen-arm.cc | 5 ++- src/codegen-inl.h | 4 ++ src/compilation-cache.cc | 21 ++++++---- src/compilation-cache.h | 3 +- src/compiler.cc | 14 ++++++- src/compiler.h | 13 ++++++- src/full-codegen.h | 3 ++ src/ia32/codegen-ia32.cc | 10 ++++- src/ia32/codegen-ia32.h | 1 + src/ia32/full-codegen-ia32.cc | 4 +- src/objects-inl.h | 12 ++++++ src/objects.cc | 37 +++++++++++++----- src/objects.h | 11 +++++- src/parser.cc | 19 ++++++++-- src/parser.h | 4 +- src/runtime.cc | 37 ++++++++++++------ src/runtime.h | 4 +- src/v8globals.h | 6 +++ src/x64/codegen-x64.cc | 10 ++++- src/x64/codegen-x64.h | 1 + src/x64/full-codegen-x64.cc | 4 +- test/mjsunit/strict-mode-eval.js | 82 ++++++++++++++++++++++++++++++++++++++++ 24 files changed, 265 insertions(+), 51 deletions(-) create mode 100644 test/mjsunit/strict-mode-eval.js diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 5f2fa32..1284223 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -4177,7 +4177,10 @@ void CodeGenerator::VisitCall(Call* node) { __ 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 @@ void CodeGenerator::VisitCall(Call* node) { __ 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. diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index 589e704..8f46256 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -287,6 +287,7 @@ class CodeGenerator: public AstVisitor { // Accessors inline bool is_eval(); inline Scope* scope(); + inline StrictModeFlag strict_mode_flag(); // Generating deferred code. void ProcessDeferred(); diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 50c715f..ff446c5 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1926,7 +1926,10 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ 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. diff --git a/src/codegen-inl.h b/src/codegen-inl.h index 6534e7f..5467789 100644 --- a/src/codegen-inl.h +++ b/src/codegen-inl.h @@ -55,6 +55,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 #endif // V8_CODEGEN_INL_H_ diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc index 38438cb..cccb7a4 100644 --- a/src/compilation-cache.cc +++ b/src/compilation-cache.cc @@ -136,7 +136,8 @@ class CompilationCacheEval: public CompilationSubCache { : CompilationSubCache(generations) { } Handle Lookup(Handle source, - Handle context); + Handle context, + StrictModeFlag strict_mode); void Put(Handle source, Handle context, @@ -371,7 +372,9 @@ void CompilationCacheScript::Put(Handle source, Handle CompilationCacheEval::Lookup( - Handle source, Handle context) { + Handle source, + Handle 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 @@ Handle CompilationCacheEval::Lookup( { HandleScope scope; for (generation = 0; generation < generations(); generation++) { Handle table = GetTable(generation); - result = table->LookupEval(*source, *context); + result = table->LookupEval(*source, *context, strict_mode); if (result->IsSharedFunctionInfo()) { break; } @@ -503,18 +506,20 @@ Handle CompilationCache::LookupScript(Handle source, } -Handle CompilationCache::LookupEval(Handle source, - Handle context, - bool is_global) { +Handle CompilationCache::LookupEval( + Handle source, + Handle context, + bool is_global, + StrictModeFlag strict_mode) { if (!IsEnabled()) { return Handle::null(); } Handle 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; } diff --git a/src/compilation-cache.h b/src/compilation-cache.h index 37e21be..f779a23 100644 --- a/src/compilation-cache.h +++ b/src/compilation-cache.h @@ -51,7 +51,8 @@ class CompilationCache { // contain a script for the given source string. static Handle LookupEval(Handle source, Handle 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. diff --git a/src/compiler.cc b/src/compiler.cc index 5c18c3e..77111a8 100755 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -548,7 +548,8 @@ Handle Compiler::Compile(Handle source, Handle Compiler::CompileEval(Handle source, Handle 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 @@ Handle Compiler::CompileEval(Handle source, // Do a lookup in the compilation cache; if the entry is not there, invoke // the compiler and add the result to the cache. Handle 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 @@ Handle Compiler::CompileEval(Handle source, 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 @@ void Compiler::SetFunctionInfo(Handle function_info, *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()); } diff --git a/src/compiler.h b/src/compiler.h index 44ac9c8..9843dd6 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -49,6 +49,7 @@ class CompilationInfo BASE_EMBEDDED { 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 @@ class CompilationInfo BASE_EMBEDDED { 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 CompilationInfo BASE_EMBEDDED { class IsGlobal: public BitField {}; // Flags that can be set for lazy compilation. class IsInLoop: public BitField {}; + // Strict mode - used in eager compilation. + class IsStrict: public BitField {}; unsigned flags_; @@ -230,7 +240,8 @@ class Compiler : public AllStatic { // Compile a String source within a context for Eval. static Handle CompileEval(Handle source, Handle 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. diff --git a/src/full-codegen.h b/src/full-codegen.h index 0482ee8..2d0998d 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -531,6 +531,9 @@ class FullCodeGenerator: public AstVisitor { Handle