Make eval compilation cache calling scope sensitive.
Review URL: http://codereview.chromium.org/8518001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9984 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
7c209a555f
commit
b153dcfebf
@ -2204,7 +2204,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
|||||||
__ mov(r1, Operand(Smi::FromInt(strict_mode)));
|
__ mov(r1, Operand(Smi::FromInt(strict_mode)));
|
||||||
__ push(r1);
|
__ push(r1);
|
||||||
|
|
||||||
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
|
// Push the start position of the scope the calls resides in.
|
||||||
|
__ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
|
||||||
|
__ push(r1);
|
||||||
|
|
||||||
|
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2008 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
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
|
#include "assembler.h"
|
||||||
#include "compilation-cache.h"
|
#include "compilation-cache.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
|
|
||||||
@ -250,7 +251,8 @@ void CompilationCacheScript::Put(Handle<String> source,
|
|||||||
Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position) {
|
||||||
// Make sure not to leak the table into the surrounding handle
|
// Make sure not to leak the table into the surrounding handle
|
||||||
// scope. Otherwise, we risk keeping old tables around even after
|
// scope. Otherwise, we risk keeping old tables around even after
|
||||||
// having cleared the cache.
|
// having cleared the cache.
|
||||||
@ -259,7 +261,8 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
|||||||
{ HandleScope scope(isolate());
|
{ HandleScope scope(isolate());
|
||||||
for (generation = 0; generation < generations(); generation++) {
|
for (generation = 0; generation < generations(); generation++) {
|
||||||
Handle<CompilationCacheTable> table = GetTable(generation);
|
Handle<CompilationCacheTable> table = GetTable(generation);
|
||||||
result = table->LookupEval(*source, *context, strict_mode);
|
result = table->LookupEval(
|
||||||
|
*source, *context, strict_mode, scope_position);
|
||||||
if (result->IsSharedFunctionInfo()) {
|
if (result->IsSharedFunctionInfo()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -269,7 +272,7 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
|||||||
Handle<SharedFunctionInfo>
|
Handle<SharedFunctionInfo>
|
||||||
function_info(SharedFunctionInfo::cast(result), isolate());
|
function_info(SharedFunctionInfo::cast(result), isolate());
|
||||||
if (generation != 0) {
|
if (generation != 0) {
|
||||||
Put(source, context, function_info);
|
Put(source, context, function_info, scope_position);
|
||||||
}
|
}
|
||||||
isolate()->counters()->compilation_cache_hits()->Increment();
|
isolate()->counters()->compilation_cache_hits()->Increment();
|
||||||
return function_info;
|
return function_info;
|
||||||
@ -283,27 +286,31 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
|||||||
MaybeObject* CompilationCacheEval::TryTablePut(
|
MaybeObject* CompilationCacheEval::TryTablePut(
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info) {
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position) {
|
||||||
Handle<CompilationCacheTable> table = GetFirstTable();
|
Handle<CompilationCacheTable> table = GetFirstTable();
|
||||||
return table->PutEval(*source, *context, *function_info);
|
return table->PutEval(*source, *context, *function_info, scope_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
|
Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info) {
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position) {
|
||||||
CALL_HEAP_FUNCTION(isolate(),
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
TryTablePut(source, context, function_info),
|
TryTablePut(
|
||||||
|
source, context, function_info, scope_position),
|
||||||
CompilationCacheTable);
|
CompilationCacheTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CompilationCacheEval::Put(Handle<String> source,
|
void CompilationCacheEval::Put(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info) {
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position) {
|
||||||
HandleScope scope(isolate());
|
HandleScope scope(isolate());
|
||||||
SetFirstTable(TablePut(source, context, function_info));
|
SetFirstTable(TablePut(source, context, function_info, scope_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,16 +396,19 @@ Handle<SharedFunctionInfo> CompilationCache::LookupEval(
|
|||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position) {
|
||||||
if (!IsEnabled()) {
|
if (!IsEnabled()) {
|
||||||
return Handle<SharedFunctionInfo>::null();
|
return Handle<SharedFunctionInfo>::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> result;
|
Handle<SharedFunctionInfo> result;
|
||||||
if (is_global) {
|
if (is_global) {
|
||||||
result = eval_global_.Lookup(source, context, strict_mode);
|
result = eval_global_.Lookup(source, context, strict_mode, scope_position);
|
||||||
} else {
|
} else {
|
||||||
result = eval_contextual_.Lookup(source, context, strict_mode);
|
ASSERT(scope_position != RelocInfo::kNoPosition);
|
||||||
|
result = eval_contextual_.Lookup(
|
||||||
|
source, context, strict_mode, scope_position);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -427,16 +437,18 @@ void CompilationCache::PutScript(Handle<String> source,
|
|||||||
void CompilationCache::PutEval(Handle<String> source,
|
void CompilationCache::PutEval(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
Handle<SharedFunctionInfo> function_info) {
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position) {
|
||||||
if (!IsEnabled()) {
|
if (!IsEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleScope scope(isolate());
|
HandleScope scope(isolate());
|
||||||
if (is_global) {
|
if (is_global) {
|
||||||
eval_global_.Put(source, context, function_info);
|
eval_global_.Put(source, context, function_info, scope_position);
|
||||||
} else {
|
} else {
|
||||||
eval_contextual_.Put(source, context, function_info);
|
ASSERT(scope_position != RelocInfo::kNoPosition);
|
||||||
|
eval_contextual_.Put(source, context, function_info, scope_position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2008 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
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -123,7 +123,19 @@ class CompilationCacheScript : public CompilationSubCache {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Sub-cache for eval scripts.
|
// Sub-cache for eval scripts. Two caches for eval are used. One for eval calls
|
||||||
|
// in global contexts and one for eval calls in other contexts. The cache
|
||||||
|
// considers the following pieces of information when checking for matching
|
||||||
|
// entries:
|
||||||
|
// 1. The source string.
|
||||||
|
// 2. The shared function info of the calling function.
|
||||||
|
// 3. Whether the source should be compiled as strict code or as non-strict
|
||||||
|
// code.
|
||||||
|
// Note: Currently there are clients of CompileEval that always compile
|
||||||
|
// non-strict code even if the calling function is a strict mode function.
|
||||||
|
// More specifically these are the CompileString, DebugEvaluate and
|
||||||
|
// DebugEvaluateGlobal runtime functions.
|
||||||
|
// 4. The start position of the calling scope.
|
||||||
class CompilationCacheEval: public CompilationSubCache {
|
class CompilationCacheEval: public CompilationSubCache {
|
||||||
public:
|
public:
|
||||||
CompilationCacheEval(Isolate* isolate, int generations)
|
CompilationCacheEval(Isolate* isolate, int generations)
|
||||||
@ -131,23 +143,27 @@ class CompilationCacheEval: public CompilationSubCache {
|
|||||||
|
|
||||||
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
|
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
StrictModeFlag strict_mode);
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
void Put(Handle<String> source,
|
void Put(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info);
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MUST_USE_RESULT MaybeObject* TryTablePut(
|
MUST_USE_RESULT MaybeObject* TryTablePut(
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info);
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
// Note: Returns a new hash table if operation results in expansion.
|
// Note: Returns a new hash table if operation results in expansion.
|
||||||
Handle<CompilationCacheTable> TablePut(
|
Handle<CompilationCacheTable> TablePut(
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<SharedFunctionInfo> function_info);
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
|
||||||
};
|
};
|
||||||
@ -198,7 +214,8 @@ class CompilationCache {
|
|||||||
Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
|
Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
StrictModeFlag strict_mode);
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
// Returns the regexp data associated with the given regexp if it
|
// Returns the regexp data associated with the given regexp if it
|
||||||
// is in cache, otherwise an empty handle.
|
// is in cache, otherwise an empty handle.
|
||||||
@ -215,7 +232,8 @@ class CompilationCache {
|
|||||||
void PutEval(Handle<String> source,
|
void PutEval(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
Handle<SharedFunctionInfo> function_info);
|
Handle<SharedFunctionInfo> function_info,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
// Associate the (source, flags) pair to the given regexp data.
|
// Associate the (source, flags) pair to the given regexp data.
|
||||||
// This may overwrite an existing mapping.
|
// This may overwrite an existing mapping.
|
||||||
|
@ -533,7 +533,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
|
|||||||
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
|
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position) {
|
||||||
Isolate* isolate = source->GetIsolate();
|
Isolate* isolate = source->GetIsolate();
|
||||||
int source_length = source->length();
|
int source_length = source->length();
|
||||||
isolate->counters()->total_eval_size()->Increment(source_length);
|
isolate->counters()->total_eval_size()->Increment(source_length);
|
||||||
@ -549,7 +550,8 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
|
|||||||
result = compilation_cache->LookupEval(source,
|
result = compilation_cache->LookupEval(source,
|
||||||
context,
|
context,
|
||||||
is_global,
|
is_global,
|
||||||
strict_mode);
|
strict_mode,
|
||||||
|
scope_position);
|
||||||
|
|
||||||
if (result.is_null()) {
|
if (result.is_null()) {
|
||||||
// Create a script object describing the script to be compiled.
|
// Create a script object describing the script to be compiled.
|
||||||
@ -561,13 +563,13 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
|
|||||||
info.SetCallingContext(context);
|
info.SetCallingContext(context);
|
||||||
result = MakeFunctionInfo(&info);
|
result = MakeFunctionInfo(&info);
|
||||||
if (!result.is_null()) {
|
if (!result.is_null()) {
|
||||||
CompilationCache* compilation_cache = isolate->compilation_cache();
|
|
||||||
// If caller is strict mode, the result must be strict as well,
|
// If caller is strict mode, the result must be strict as well,
|
||||||
// but not the other way around. Consider:
|
// but not the other way around. Consider:
|
||||||
// eval("'use strict'; ...");
|
// eval("'use strict'; ...");
|
||||||
// TODO(keuchel): adapt this for extended mode.
|
// TODO(keuchel): adapt this for extended mode.
|
||||||
ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
|
ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
|
||||||
compilation_cache->PutEval(source, context, is_global, result);
|
compilation_cache->PutEval(
|
||||||
|
source, context, is_global, result, scope_position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,8 @@ class Compiler : public AllStatic {
|
|||||||
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
|
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
bool is_global,
|
bool is_global,
|
||||||
StrictModeFlag strict_mode);
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position);
|
||||||
|
|
||||||
// Compile from function info (used for lazy compilation). Returns true on
|
// Compile from function info (used for lazy compilation). Returns true on
|
||||||
// success and false if the compilation resulted in a stack overflow.
|
// success and false if the compilation resulted in a stack overflow.
|
||||||
|
@ -2152,7 +2152,10 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
|||||||
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
|
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
|
||||||
__ push(Immediate(Smi::FromInt(strict_mode)));
|
__ push(Immediate(Smi::FromInt(strict_mode)));
|
||||||
|
|
||||||
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
|
// Push the start position of the scope the calls resides in.
|
||||||
|
__ push(Immediate(Smi::FromInt(scope()->start_position())));
|
||||||
|
|
||||||
|
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2271,7 +2271,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
|||||||
__ li(a1, Operand(Smi::FromInt(strict_mode)));
|
__ li(a1, Operand(Smi::FromInt(strict_mode)));
|
||||||
__ push(a1);
|
__ push(a1);
|
||||||
|
|
||||||
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
|
// Push the start position of the scope the calls resides in.
|
||||||
|
__ li(a1, Operand(Smi::FromInt(scope()->start_position())));
|
||||||
|
__ push(a1);
|
||||||
|
|
||||||
|
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10298,74 +10298,83 @@ class StringSharedKey : public HashTableKey {
|
|||||||
public:
|
public:
|
||||||
StringSharedKey(String* source,
|
StringSharedKey(String* source,
|
||||||
SharedFunctionInfo* shared,
|
SharedFunctionInfo* shared,
|
||||||
StrictModeFlag strict_mode)
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position)
|
||||||
: source_(source),
|
: source_(source),
|
||||||
shared_(shared),
|
shared_(shared),
|
||||||
strict_mode_(strict_mode) { }
|
strict_mode_(strict_mode),
|
||||||
|
scope_position_(scope_position) { }
|
||||||
|
|
||||||
bool IsMatch(Object* other) {
|
bool IsMatch(Object* other) {
|
||||||
if (!other->IsFixedArray()) return false;
|
if (!other->IsFixedArray()) return false;
|
||||||
FixedArray* pair = FixedArray::cast(other);
|
FixedArray* other_array = FixedArray::cast(other);
|
||||||
SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
|
SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
|
||||||
if (shared != shared_) return false;
|
if (shared != shared_) return false;
|
||||||
int strict_unchecked = Smi::cast(pair->get(2))->value();
|
int strict_unchecked = Smi::cast(other_array->get(2))->value();
|
||||||
ASSERT(strict_unchecked == kStrictMode ||
|
ASSERT(strict_unchecked == kStrictMode ||
|
||||||
strict_unchecked == kNonStrictMode);
|
strict_unchecked == kNonStrictMode);
|
||||||
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
|
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
|
||||||
if (strict_mode != strict_mode_) return false;
|
if (strict_mode != strict_mode_) return false;
|
||||||
String* source = String::cast(pair->get(1));
|
int scope_position = Smi::cast(other_array->get(3))->value();
|
||||||
|
if (scope_position != scope_position_) return false;
|
||||||
|
String* source = String::cast(other_array->get(1));
|
||||||
return source->Equals(source_);
|
return source->Equals(source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t StringSharedHashHelper(String* source,
|
static uint32_t StringSharedHashHelper(String* source,
|
||||||
SharedFunctionInfo* shared,
|
SharedFunctionInfo* shared,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position) {
|
||||||
uint32_t hash = source->Hash();
|
uint32_t hash = source->Hash();
|
||||||
if (shared->HasSourceCode()) {
|
if (shared->HasSourceCode()) {
|
||||||
// Instead of using the SharedFunctionInfo pointer in the hash
|
// Instead of using the SharedFunctionInfo pointer in the hash
|
||||||
// code computation, we use a combination of the hash of the
|
// code computation, we use a combination of the hash of the
|
||||||
// script source code and the start and end positions. We do
|
// script source code and the start position of the calling scope.
|
||||||
// this to ensure that the cache entries can survive garbage
|
// We do this to ensure that the cache entries can survive garbage
|
||||||
// collection.
|
// collection.
|
||||||
Script* script = Script::cast(shared->script());
|
Script* script = Script::cast(shared->script());
|
||||||
hash ^= String::cast(script->source())->Hash();
|
hash ^= String::cast(script->source())->Hash();
|
||||||
if (strict_mode == kStrictMode) hash ^= 0x8000;
|
if (strict_mode == kStrictMode) hash ^= 0x8000;
|
||||||
hash += shared->start_position();
|
hash += scope_position;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Hash() {
|
uint32_t Hash() {
|
||||||
return StringSharedHashHelper(source_, shared_, strict_mode_);
|
return StringSharedHashHelper(
|
||||||
|
source_, shared_, strict_mode_, scope_position_);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t HashForObject(Object* obj) {
|
uint32_t HashForObject(Object* obj) {
|
||||||
FixedArray* pair = FixedArray::cast(obj);
|
FixedArray* other_array = FixedArray::cast(obj);
|
||||||
SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
|
SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
|
||||||
String* source = String::cast(pair->get(1));
|
String* source = String::cast(other_array->get(1));
|
||||||
int strict_unchecked = Smi::cast(pair->get(2))->value();
|
int strict_unchecked = Smi::cast(other_array->get(2))->value();
|
||||||
ASSERT(strict_unchecked == kStrictMode ||
|
ASSERT(strict_unchecked == kStrictMode ||
|
||||||
strict_unchecked == kNonStrictMode);
|
strict_unchecked == kNonStrictMode);
|
||||||
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
|
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
|
||||||
return StringSharedHashHelper(source, shared, strict_mode);
|
int scope_position = Smi::cast(other_array->get(3))->value();
|
||||||
|
return StringSharedHashHelper(source, shared, strict_mode, scope_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* AsObject() {
|
MUST_USE_RESULT MaybeObject* AsObject() {
|
||||||
Object* obj;
|
Object* obj;
|
||||||
{ MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3);
|
{ MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
|
||||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||||
}
|
}
|
||||||
FixedArray* pair = FixedArray::cast(obj);
|
FixedArray* other_array = FixedArray::cast(obj);
|
||||||
pair->set(0, shared_);
|
other_array->set(0, shared_);
|
||||||
pair->set(1, source_);
|
other_array->set(1, source_);
|
||||||
pair->set(2, Smi::FromInt(strict_mode_));
|
other_array->set(2, Smi::FromInt(strict_mode_));
|
||||||
return pair;
|
other_array->set(3, Smi::FromInt(scope_position_));
|
||||||
|
return other_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String* source_;
|
String* source_;
|
||||||
SharedFunctionInfo* shared_;
|
SharedFunctionInfo* shared_;
|
||||||
StrictModeFlag strict_mode_;
|
StrictModeFlag strict_mode_;
|
||||||
|
int scope_position_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -11520,8 +11529,12 @@ Object* CompilationCacheTable::Lookup(String* src) {
|
|||||||
|
|
||||||
Object* CompilationCacheTable::LookupEval(String* src,
|
Object* CompilationCacheTable::LookupEval(String* src,
|
||||||
Context* context,
|
Context* context,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
StringSharedKey key(src, context->closure()->shared(), strict_mode);
|
int scope_position) {
|
||||||
|
StringSharedKey key(src,
|
||||||
|
context->closure()->shared(),
|
||||||
|
strict_mode,
|
||||||
|
scope_position);
|
||||||
int entry = FindEntry(&key);
|
int entry = FindEntry(&key);
|
||||||
if (entry == kNotFound) return GetHeap()->undefined_value();
|
if (entry == kNotFound) return GetHeap()->undefined_value();
|
||||||
return get(EntryToIndex(entry) + 1);
|
return get(EntryToIndex(entry) + 1);
|
||||||
@ -11556,10 +11569,12 @@ MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
|
|||||||
|
|
||||||
MaybeObject* CompilationCacheTable::PutEval(String* src,
|
MaybeObject* CompilationCacheTable::PutEval(String* src,
|
||||||
Context* context,
|
Context* context,
|
||||||
SharedFunctionInfo* value) {
|
SharedFunctionInfo* value,
|
||||||
|
int scope_position) {
|
||||||
StringSharedKey key(src,
|
StringSharedKey key(src,
|
||||||
context->closure()->shared(),
|
context->closure()->shared(),
|
||||||
value->strict_mode_flag());
|
value->strict_mode_flag(),
|
||||||
|
scope_position);
|
||||||
Object* obj;
|
Object* obj;
|
||||||
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
|
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
|
||||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||||
|
@ -5849,12 +5849,16 @@ class CompilationCacheTable: public HashTable<CompilationCacheShape,
|
|||||||
public:
|
public:
|
||||||
// Find cached value for a string key, otherwise return null.
|
// Find cached value for a string key, otherwise return null.
|
||||||
Object* Lookup(String* src);
|
Object* Lookup(String* src);
|
||||||
Object* LookupEval(String* src, Context* context, StrictModeFlag strict_mode);
|
Object* LookupEval(String* src,
|
||||||
|
Context* context,
|
||||||
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position);
|
||||||
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
|
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
|
||||||
MaybeObject* Put(String* src, Object* value);
|
MaybeObject* Put(String* src, Object* value);
|
||||||
MaybeObject* PutEval(String* src,
|
MaybeObject* PutEval(String* src,
|
||||||
Context* context,
|
Context* context,
|
||||||
SharedFunctionInfo* value);
|
SharedFunctionInfo* value,
|
||||||
|
int scope_position);
|
||||||
MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
|
MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
|
||||||
|
|
||||||
// Remove given value from cache.
|
// Remove given value from cache.
|
||||||
|
@ -9477,10 +9477,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile source string in the global context.
|
// Compile source string in the global context.
|
||||||
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
|
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
|
||||||
context,
|
source, context, true, kNonStrictMode, RelocInfo::kNoPosition);
|
||||||
true,
|
|
||||||
kNonStrictMode);
|
|
||||||
if (shared.is_null()) return Failure::Exception();
|
if (shared.is_null()) return Failure::Exception();
|
||||||
Handle<JSFunction> fun =
|
Handle<JSFunction> fun =
|
||||||
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
|
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
|
||||||
@ -9493,7 +9491,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
|
|||||||
static ObjectPair CompileGlobalEval(Isolate* isolate,
|
static ObjectPair CompileGlobalEval(Isolate* isolate,
|
||||||
Handle<String> source,
|
Handle<String> source,
|
||||||
Handle<Object> receiver,
|
Handle<Object> receiver,
|
||||||
StrictModeFlag strict_mode) {
|
StrictModeFlag strict_mode,
|
||||||
|
int scope_position) {
|
||||||
Handle<Context> context = Handle<Context>(isolate->context());
|
Handle<Context> context = Handle<Context>(isolate->context());
|
||||||
Handle<Context> global_context = Handle<Context>(context->global_context());
|
Handle<Context> global_context = Handle<Context>(context->global_context());
|
||||||
|
|
||||||
@ -9511,7 +9510,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
|
|||||||
source,
|
source,
|
||||||
Handle<Context>(isolate->context()),
|
Handle<Context>(isolate->context()),
|
||||||
context->IsGlobalContext(),
|
context->IsGlobalContext(),
|
||||||
strict_mode);
|
strict_mode,
|
||||||
|
scope_position);
|
||||||
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
|
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
|
||||||
Handle<JSFunction> compiled =
|
Handle<JSFunction> compiled =
|
||||||
isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
||||||
@ -9521,7 +9521,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
|
|||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
|
RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
|
||||||
ASSERT(args.length() == 4);
|
ASSERT(args.length() == 5);
|
||||||
|
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
Handle<Object> callee = args.at<Object>(0);
|
Handle<Object> callee = args.at<Object>(0);
|
||||||
@ -9537,10 +9537,12 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CONVERT_STRICT_MODE_ARG(strict_mode, 3);
|
CONVERT_STRICT_MODE_ARG(strict_mode, 3);
|
||||||
|
ASSERT(args[4]->IsSmi());
|
||||||
return CompileGlobalEval(isolate,
|
return CompileGlobalEval(isolate,
|
||||||
args.at<String>(1),
|
args.at<String>(1),
|
||||||
args.at<Object>(2),
|
args.at<Object>(2),
|
||||||
strict_mode);
|
strict_mode,
|
||||||
|
args.smi_at(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -12154,7 +12156,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
|||||||
Compiler::CompileEval(function_source,
|
Compiler::CompileEval(function_source,
|
||||||
context,
|
context,
|
||||||
context->IsGlobalContext(),
|
context->IsGlobalContext(),
|
||||||
kNonStrictMode);
|
kNonStrictMode,
|
||||||
|
RelocInfo::kNoPosition);
|
||||||
if (shared.is_null()) return Failure::Exception();
|
if (shared.is_null()) return Failure::Exception();
|
||||||
Handle<JSFunction> compiled_function =
|
Handle<JSFunction> compiled_function =
|
||||||
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
|
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
|
||||||
@ -12247,7 +12250,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
|
|||||||
// Currently, the eval code will be executed in non-strict mode,
|
// Currently, the eval code will be executed in non-strict mode,
|
||||||
// even in the strict code context.
|
// even in the strict code context.
|
||||||
Handle<SharedFunctionInfo> shared =
|
Handle<SharedFunctionInfo> shared =
|
||||||
Compiler::CompileEval(source, context, is_global, kNonStrictMode);
|
Compiler::CompileEval(source,
|
||||||
|
context,
|
||||||
|
is_global,
|
||||||
|
kNonStrictMode,
|
||||||
|
RelocInfo::kNoPosition);
|
||||||
if (shared.is_null()) return Failure::Exception();
|
if (shared.is_null()) return Failure::Exception();
|
||||||
Handle<JSFunction> compiled_function =
|
Handle<JSFunction> compiled_function =
|
||||||
Handle<JSFunction>(
|
Handle<JSFunction>(
|
||||||
|
@ -259,7 +259,7 @@ namespace internal {
|
|||||||
\
|
\
|
||||||
/* Eval */ \
|
/* Eval */ \
|
||||||
F(GlobalReceiver, 1, 1) \
|
F(GlobalReceiver, 1, 1) \
|
||||||
F(ResolvePossiblyDirectEval, 4, 2) \
|
F(ResolvePossiblyDirectEval, 5, 2) \
|
||||||
\
|
\
|
||||||
F(SetProperty, -1 /* 4 or 5 */, 1) \
|
F(SetProperty, -1 /* 4 or 5 */, 1) \
|
||||||
F(DefineOrRedefineDataProperty, 4, 1) \
|
F(DefineOrRedefineDataProperty, 4, 1) \
|
||||||
|
@ -2096,7 +2096,10 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
|||||||
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
|
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
|
||||||
__ Push(Smi::FromInt(strict_mode));
|
__ Push(Smi::FromInt(strict_mode));
|
||||||
|
|
||||||
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
|
// Push the start position of the scope the calls resides in.
|
||||||
|
__ Push(Smi::FromInt(scope()->start_position()));
|
||||||
|
|
||||||
|
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user