Commit 666c4be2 authored by keuchel@chromium.org's avatar keuchel@chromium.org

Reapply r9673 "Scope tree serialization and ScopeIterator cleanup."

This also includes the two fixes from r9674 and r9675. Here's the diff
to the previous CL.

 --- a/src/runtime.cc
 +++ b/src/runtime.cc
 @@ -11133,17 +11133,26 @@ class ScopeIterator {
        context_(Context::cast(frame->context())),
        nested_scope_chain_(4) {

 +    // Catch the case when the debugger stops in an internal function.
 +    Handle<SharedFunctionInfo> shared_info(function_->shared());
 +    if (shared_info->script() == isolate->heap()->undefined_value()) {
 +      if (shared_info->scope_info()->HasContext()) Next();
 +      return;
 +    }
 +
      // Check whether we are in global code or function code. If there is a stack
      // slot for .result then this function has been created for evaluating
      // global code and it is not a real function.
      // Checking for the existence of .result seems fragile, but the scope info
      // saved with the code object does not otherwise have that information.
 -    int index = function_->shared()->scope_info()->
 +    int index = shared_info->scope_info()->
          StackSlotIndex(isolate_->heap()->result_symbol());

      // Reparse the code and analyze the scopes.
      ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
 -    Handle<SharedFunctionInfo> shared_info(function_->shared());
      Handle<Script> script(Script::cast(shared_info->script()));
      Scope* scope;
      if (index >= 0) {

Review URL: http://codereview.chromium.org/8344046

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9734 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 937006f7
...@@ -111,6 +111,16 @@ ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels) ...@@ -111,6 +111,16 @@ ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels)
} }
int FunctionLiteral::start_position() const {
return scope()->start_position();
}
int FunctionLiteral::end_position() const {
return scope()->end_position();
}
bool FunctionLiteral::strict_mode() const { bool FunctionLiteral::strict_mode() const {
return scope()->is_strict_mode(); return scope()->is_strict_mode();
} }
......
...@@ -1617,8 +1617,6 @@ class FunctionLiteral: public Expression { ...@@ -1617,8 +1617,6 @@ class FunctionLiteral: public Expression {
bool has_only_simple_this_property_assignments, bool has_only_simple_this_property_assignments,
Handle<FixedArray> this_property_assignments, Handle<FixedArray> this_property_assignments,
int num_parameters, int num_parameters,
int start_position,
int end_position,
Type type, Type type,
bool has_duplicate_parameters) bool has_duplicate_parameters)
: Expression(isolate), : Expression(isolate),
...@@ -1631,8 +1629,6 @@ class FunctionLiteral: public Expression { ...@@ -1631,8 +1629,6 @@ class FunctionLiteral: public Expression {
has_only_simple_this_property_assignments), has_only_simple_this_property_assignments),
this_property_assignments_(this_property_assignments), this_property_assignments_(this_property_assignments),
num_parameters_(num_parameters), num_parameters_(num_parameters),
start_position_(start_position),
end_position_(end_position),
function_token_position_(RelocInfo::kNoPosition), function_token_position_(RelocInfo::kNoPosition),
inferred_name_(HEAP->empty_string()), inferred_name_(HEAP->empty_string()),
is_expression_(type != DECLARATION), is_expression_(type != DECLARATION),
...@@ -1648,8 +1644,8 @@ class FunctionLiteral: public Expression { ...@@ -1648,8 +1644,8 @@ class FunctionLiteral: public Expression {
ZoneList<Statement*>* body() const { return body_; } ZoneList<Statement*>* body() const { return body_; }
void set_function_token_position(int pos) { function_token_position_ = pos; } void set_function_token_position(int pos) { function_token_position_ = pos; }
int function_token_position() const { return function_token_position_; } int function_token_position() const { return function_token_position_; }
int start_position() const { return start_position_; } int start_position() const;
int end_position() const { return end_position_; } int end_position() const;
bool is_expression() const { return is_expression_; } bool is_expression() const { return is_expression_; }
bool is_anonymous() const { return is_anonymous_; } bool is_anonymous() const { return is_anonymous_; }
bool strict_mode() const; bool strict_mode() const;
......
...@@ -194,7 +194,8 @@ class Context: public FixedArray { ...@@ -194,7 +194,8 @@ class Context: public FixedArray {
PREVIOUS_INDEX, PREVIOUS_INDEX,
// The extension slot is used for either the global object (in global // The extension slot is used for either the global object (in global
// contexts), eval extension object (function contexts), subject of with // contexts), eval extension object (function contexts), subject of with
// (with contexts), or the variable name (catch contexts). // (with contexts), or the variable name (catch contexts), the serialized
// scope info (block contexts).
EXTENSION_INDEX, EXTENSION_INDEX,
GLOBAL_INDEX, GLOBAL_INDEX,
MIN_CONTEXT_SLOTS, MIN_CONTEXT_SLOTS,
......
...@@ -3046,6 +3046,9 @@ class SerializedScopeInfo : public FixedArray { ...@@ -3046,6 +3046,9 @@ class SerializedScopeInfo : public FixedArray {
return reinterpret_cast<SerializedScopeInfo*>(object); return reinterpret_cast<SerializedScopeInfo*>(object);
} }
// Return the type of this scope.
ScopeType Type();
// Does this scope call eval? // Does this scope call eval?
bool CallsEval(); bool CallsEval();
...@@ -3061,6 +3064,9 @@ class SerializedScopeInfo : public FixedArray { ...@@ -3061,6 +3064,9 @@ class SerializedScopeInfo : public FixedArray {
// Return if this has context slots besides MIN_CONTEXT_SLOTS; // Return if this has context slots besides MIN_CONTEXT_SLOTS;
bool HasHeapAllocatedLocals(); bool HasHeapAllocatedLocals();
// Return if contexts are allocated for this scope.
bool HasContext();
// Lookup support for serialized scope info. Returns the // Lookup support for serialized scope info. Returns the
// the stack slot index for a given slot name if the slot is // the stack slot index for a given slot name if the slot is
// present; otherwise returns a value < 0. The name must be a symbol // present; otherwise returns a value < 0. The name must be a symbol
......
This diff is collapsed.
...@@ -678,7 +678,7 @@ class Parser { ...@@ -678,7 +678,7 @@ class Parser {
return &empty; return &empty;
} }
Scope* NewScope(Scope* parent, Scope::Type type); Scope* NewScope(Scope* parent, ScopeType type);
Handle<String> LookupSymbol(int symbol_id); Handle<String> LookupSymbol(int symbol_id);
......
This diff is collapsed.
...@@ -51,6 +51,7 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -51,6 +51,7 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
: function_name_(FACTORY->empty_symbol()), : function_name_(FACTORY->empty_symbol()),
calls_eval_(scope->calls_eval()), calls_eval_(scope->calls_eval()),
is_strict_mode_(scope->is_strict_mode()), is_strict_mode_(scope->is_strict_mode()),
type_(scope->type()),
parameters_(scope->num_parameters()), parameters_(scope->num_parameters()),
stack_slots_(scope->num_stack_slots()), stack_slots_(scope->num_stack_slots()),
context_slots_(scope->num_heap_slots()), context_slots_(scope->num_heap_slots()),
...@@ -150,6 +151,10 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -150,6 +151,10 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
// //
// - calls eval boolean flag // - calls eval boolean flag
// //
// - is strict mode scope
//
// - scope type
//
// - number of variables in the context object (smi) (= function context // - number of variables in the context object (smi) (= function context
// slot index + 1) // slot index + 1)
// - list of pairs (name, Var mode) of context-allocated variables (starting // - list of pairs (name, Var mode) of context-allocated variables (starting
...@@ -181,8 +186,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -181,8 +186,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
// present) // present)
static inline Object** ReadInt(Object** p, int* x) { template <class T>
*x = (reinterpret_cast<Smi*>(*p++))->value(); static inline Object** ReadInt(Object** p, T* x) {
*x = static_cast<T>((reinterpret_cast<Smi*>(*p++))->value());
return p; return p;
} }
...@@ -193,20 +199,21 @@ static inline Object** ReadBool(Object** p, bool* x) { ...@@ -193,20 +199,21 @@ static inline Object** ReadBool(Object** p, bool* x) {
} }
static inline Object** ReadSymbol(Object** p, Handle<String>* s) { template <class T>
*s = Handle<String>(reinterpret_cast<String*>(*p++)); static inline Object** ReadObject(Object** p, Handle<T>* s) {
*s = Handle<T>::cast(Handle<Object>(*p++));
return p; return p;
} }
template <class Allocator> template <class Allocator, class T>
static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) { static Object** ReadList(Object** p, List<Handle<T>, Allocator >* list) {
ASSERT(list->is_empty()); ASSERT(list->is_empty());
int n; int n;
p = ReadInt(p, &n); p = ReadInt(p, &n);
while (n-- > 0) { while (n-- > 0) {
Handle<String> s; Handle<T> s;
p = ReadSymbol(p, &s); p = ReadObject(p, &s);
list->Add(s); list->Add(s);
} }
return p; return p;
...@@ -223,7 +230,7 @@ static Object** ReadList(Object** p, ...@@ -223,7 +230,7 @@ static Object** ReadList(Object** p,
while (n-- > 0) { while (n-- > 0) {
Handle<String> s; Handle<String> s;
int m; int m;
p = ReadSymbol(p, &s); p = ReadObject(p, &s);
p = ReadInt(p, &m); p = ReadInt(p, &m);
list->Add(s); list->Add(s);
modes->Add(static_cast<VariableMode>(m)); modes->Add(static_cast<VariableMode>(m));
...@@ -242,9 +249,10 @@ ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data) ...@@ -242,9 +249,10 @@ ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
if (data->length() > 0) { if (data->length() > 0) {
Object** p0 = data->data_start(); Object** p0 = data->data_start();
Object** p = p0; Object** p = p0;
p = ReadSymbol(p, &function_name_); p = ReadObject(p, &function_name_);
p = ReadBool(p, &calls_eval_); p = ReadBool(p, &calls_eval_);
p = ReadBool(p, &is_strict_mode_); p = ReadBool(p, &is_strict_mode_);
p = ReadInt(p, &type_);
p = ReadList<Allocator>(p, &context_slots_, &context_modes_); p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
p = ReadList<Allocator>(p, &parameters_); p = ReadList<Allocator>(p, &parameters_);
p = ReadList<Allocator>(p, &stack_slots_); p = ReadList<Allocator>(p, &stack_slots_);
...@@ -265,18 +273,19 @@ static inline Object** WriteBool(Object** p, bool b) { ...@@ -265,18 +273,19 @@ static inline Object** WriteBool(Object** p, bool b) {
} }
static inline Object** WriteSymbol(Object** p, Handle<String> s) { template <class T>
static inline Object** WriteObject(Object** p, Handle<T> s) {
*p++ = *s; *p++ = *s;
return p; return p;
} }
template <class Allocator> template <class Allocator, class T>
static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) { static Object** WriteList(Object** p, List<Handle<T>, Allocator >* list) {
const int n = list->length(); const int n = list->length();
p = WriteInt(p, n); p = WriteInt(p, n);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
p = WriteSymbol(p, list->at(i)); p = WriteObject(p, list->at(i));
} }
return p; return p;
} }
...@@ -289,7 +298,7 @@ static Object** WriteList(Object** p, ...@@ -289,7 +298,7 @@ static Object** WriteList(Object** p,
const int n = list->length(); const int n = list->length();
p = WriteInt(p, n); p = WriteInt(p, n);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
p = WriteSymbol(p, list->at(i)); p = WriteObject(p, list->at(i));
p = WriteInt(p, modes->at(i)); p = WriteInt(p, modes->at(i));
} }
return p; return p;
...@@ -298,8 +307,9 @@ static Object** WriteList(Object** p, ...@@ -298,8 +307,9 @@ static Object** WriteList(Object** p,
template<class Allocator> template<class Allocator>
Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
// function name, calls eval, is_strict_mode, length for 3 tables: // function name, calls eval, is_strict_mode, scope type,
const int extra_slots = 1 + 1 + 1 + 3; // length for 3 tables:
const int extra_slots = 1 + 1 + 1 + 1 + 3;
int length = extra_slots + int length = extra_slots +
context_slots_.length() * 2 + context_slots_.length() * 2 +
parameters_.length() + parameters_.length() +
...@@ -311,9 +321,10 @@ Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { ...@@ -311,9 +321,10 @@ Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
Object** p0 = data->data_start(); Object** p0 = data->data_start();
Object** p = p0; Object** p = p0;
p = WriteSymbol(p, function_name_); p = WriteObject(p, function_name_);
p = WriteBool(p, calls_eval_); p = WriteBool(p, calls_eval_);
p = WriteBool(p, is_strict_mode_); p = WriteBool(p, is_strict_mode_);
p = WriteInt(p, type_);
p = WriteList(p, &context_slots_, &context_modes_); p = WriteList(p, &context_slots_, &context_modes_);
p = WriteList(p, &parameters_); p = WriteList(p, &parameters_);
p = WriteList(p, &stack_slots_); p = WriteList(p, &stack_slots_);
...@@ -361,8 +372,8 @@ SerializedScopeInfo* SerializedScopeInfo::Empty() { ...@@ -361,8 +372,8 @@ SerializedScopeInfo* SerializedScopeInfo::Empty() {
Object** SerializedScopeInfo::ContextEntriesAddr() { Object** SerializedScopeInfo::ContextEntriesAddr() {
ASSERT(length() > 0); ASSERT(length() > 0);
// +3 for function name, calls eval, strict mode. // +4 for function name, calls eval, strict mode, scope type.
return data_start() + 3; return data_start() + 4;
} }
...@@ -406,6 +417,16 @@ bool SerializedScopeInfo::IsStrictMode() { ...@@ -406,6 +417,16 @@ bool SerializedScopeInfo::IsStrictMode() {
} }
ScopeType SerializedScopeInfo::Type() {
ASSERT(length() > 0);
// +3 for function name, calls eval, strict mode.
Object** p = data_start() + 3;
ScopeType type;
p = ReadInt(p, &type);
return type;
}
int SerializedScopeInfo::NumberOfStackSlots() { int SerializedScopeInfo::NumberOfStackSlots() {
if (length() > 0) { if (length() > 0) {
Object** p = StackSlotEntriesAddr(); Object** p = StackSlotEntriesAddr();
...@@ -439,6 +460,12 @@ bool SerializedScopeInfo::HasHeapAllocatedLocals() { ...@@ -439,6 +460,12 @@ bool SerializedScopeInfo::HasHeapAllocatedLocals() {
} }
bool SerializedScopeInfo::HasContext() {
return HasHeapAllocatedLocals() ||
Type() == WITH_SCOPE;
}
int SerializedScopeInfo::StackSlotIndex(String* name) { int SerializedScopeInfo::StackSlotIndex(String* name) {
ASSERT(name->IsSymbol()); ASSERT(name->IsSymbol());
if (length() > 0) { if (length() > 0) {
......
...@@ -35,17 +35,10 @@ ...@@ -35,17 +35,10 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Scope information represents information about a functions's // ScopeInfo represents information about different scopes of a source
// scopes (currently only one, because we don't do any inlining) // program and the allocation of the scope's variables. Scope information
// and the allocation of the scope's variables. Scope information // is stored in a compressed form in SerializedScopeInfo objects and is used
// is stored in a compressed form in FixedArray objects and is used
// at runtime (stack dumps, deoptimization, etc.). // at runtime (stack dumps, deoptimization, etc.).
//
// Historical note: In other VMs built by this team, ScopeInfo was
// usually called DebugInfo since the information was used (among
// other things) for on-demand debugging (Self, Smalltalk). However,
// DebugInfo seems misleading, since this information is primarily used
// in debugging-unrelated contexts.
// Forward defined as // Forward defined as
// template <class Allocator = FreeStoreAllocationPolicy> class ScopeInfo; // template <class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
...@@ -83,6 +76,7 @@ class ScopeInfo BASE_EMBEDDED { ...@@ -83,6 +76,7 @@ class ScopeInfo BASE_EMBEDDED {
Handle<String> LocalName(int i) const; Handle<String> LocalName(int i) const;
int NumberOfLocals() const; int NumberOfLocals() const;
ScopeType type() const { return type_; }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Debugging support // Debugging support
...@@ -94,6 +88,7 @@ class ScopeInfo BASE_EMBEDDED { ...@@ -94,6 +88,7 @@ class ScopeInfo BASE_EMBEDDED {
Handle<String> function_name_; Handle<String> function_name_;
bool calls_eval_; bool calls_eval_;
bool is_strict_mode_; bool is_strict_mode_;
ScopeType type_;
List<Handle<String>, Allocator > parameters_; List<Handle<String>, Allocator > parameters_;
List<Handle<String>, Allocator > stack_slots_; List<Handle<String>, Allocator > stack_slots_;
List<Handle<String>, Allocator > context_slots_; List<Handle<String>, Allocator > context_slots_;
......
...@@ -114,7 +114,7 @@ Variable* VariableMap::Lookup(Handle<String> name) { ...@@ -114,7 +114,7 @@ Variable* VariableMap::Lookup(Handle<String> name) {
// Dummy constructor // Dummy constructor
Scope::Scope(Type type) Scope::Scope(ScopeType type)
: isolate_(Isolate::Current()), : isolate_(Isolate::Current()),
inner_scopes_(0), inner_scopes_(0),
variables_(false), variables_(false),
...@@ -127,7 +127,7 @@ Scope::Scope(Type type) ...@@ -127,7 +127,7 @@ Scope::Scope(Type type)
} }
Scope::Scope(Scope* outer_scope, Type type) Scope::Scope(Scope* outer_scope, ScopeType type)
: isolate_(Isolate::Current()), : isolate_(Isolate::Current()),
inner_scopes_(4), inner_scopes_(4),
variables_(), variables_(),
...@@ -146,7 +146,7 @@ Scope::Scope(Scope* outer_scope, Type type) ...@@ -146,7 +146,7 @@ Scope::Scope(Scope* outer_scope, Type type)
Scope::Scope(Scope* inner_scope, Scope::Scope(Scope* inner_scope,
Type type, ScopeType type,
Handle<SerializedScopeInfo> scope_info) Handle<SerializedScopeInfo> scope_info)
: isolate_(Isolate::Current()), : isolate_(Isolate::Current()),
inner_scopes_(4), inner_scopes_(4),
...@@ -185,7 +185,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) ...@@ -185,7 +185,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
} }
void Scope::SetDefaults(Type type, void Scope::SetDefaults(ScopeType type,
Scope* outer_scope, Scope* outer_scope,
Handle<SerializedScopeInfo> scope_info) { Handle<SerializedScopeInfo> scope_info) {
outer_scope_ = outer_scope; outer_scope_ = outer_scope;
...@@ -208,6 +208,8 @@ void Scope::SetDefaults(Type type, ...@@ -208,6 +208,8 @@ void Scope::SetDefaults(Type type,
num_stack_slots_ = 0; num_stack_slots_ = 0;
num_heap_slots_ = 0; num_heap_slots_ = 0;
scope_info_ = scope_info; scope_info_ = scope_info;
start_position_ = RelocInfo::kNoPosition;
end_position_ = RelocInfo::kNoPosition;
} }
...@@ -630,15 +632,33 @@ Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { ...@@ -630,15 +632,33 @@ Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() {
} }
void Scope::GetNestedScopeChain(
List<Handle<SerializedScopeInfo> >* chain,
int position) {
chain->Add(Handle<SerializedScopeInfo>(GetSerializedScopeInfo()));
for (int i = 0; i < inner_scopes_.length(); i++) {
Scope* scope = inner_scopes_[i];
int beg_pos = scope->start_position();
int end_pos = scope->end_position();
ASSERT(beg_pos >= 0 && end_pos >= 0);
if (beg_pos <= position && position <= end_pos) {
scope->GetNestedScopeChain(chain, position);
return;
}
}
}
#ifdef DEBUG #ifdef DEBUG
static const char* Header(Scope::Type type) { static const char* Header(ScopeType type) {
switch (type) { switch (type) {
case Scope::EVAL_SCOPE: return "eval"; case EVAL_SCOPE: return "eval";
case Scope::FUNCTION_SCOPE: return "function"; case FUNCTION_SCOPE: return "function";
case Scope::GLOBAL_SCOPE: return "global"; case GLOBAL_SCOPE: return "global";
case Scope::CATCH_SCOPE: return "catch"; case CATCH_SCOPE: return "catch";
case Scope::BLOCK_SCOPE: return "block"; case BLOCK_SCOPE: return "block";
case Scope::WITH_SCOPE: return "with"; case WITH_SCOPE: return "with";
} }
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
......
...@@ -89,16 +89,7 @@ class Scope: public ZoneObject { ...@@ -89,16 +89,7 @@ class Scope: public ZoneObject {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Construction // Construction
enum Type { Scope(Scope* outer_scope, ScopeType type);
EVAL_SCOPE, // The top-level scope for an eval source.
FUNCTION_SCOPE, // The top-level scope for a function.
GLOBAL_SCOPE, // The top-level scope for a program or a top-level eval.
CATCH_SCOPE, // The scope introduced by catch.
BLOCK_SCOPE, // The scope introduced by a new block.
WITH_SCOPE // The scope introduced by with.
};
Scope(Scope* outer_scope, Type type);
// Compute top scope and allocate variables. For lazy compilation the top // Compute top scope and allocate variables. For lazy compilation the top
// scope only contains the single lazily compiled function, so this // scope only contains the single lazily compiled function, so this
...@@ -206,6 +197,37 @@ class Scope: public ZoneObject { ...@@ -206,6 +197,37 @@ class Scope: public ZoneObject {
strict_mode_ = FLAG_strict_mode; strict_mode_ = FLAG_strict_mode;
} }
// Position in the source where this scope begins and ends.
//
// * For the scope of a with statement
// with (obj) stmt
// start position: start position of first token of 'stmt'
// end position: end position of last token of 'stmt'
// * For the scope of a block
// { stmts }
// start position: start position of '{'
// end position: end position of '}'
// * For the scope of a function literal or decalaration
// function fun(a,b) { stmts }
// start position: start position of '('
// end position: end position of '}'
// * For the scope of a catch block
// try { stms } catch(e) { stmts }
// start position: start position of '('
// end position: end position of ')'
// * For the scope of a for-statement
// for (let x ...) stmt
// start position: start position of '('
// end position: end position of last token of 'stmt'
int start_position() const { return start_position_; }
void set_start_position(int statement_pos) {
start_position_ = statement_pos;
}
int end_position() const { return end_position_; }
void set_end_position(int statement_pos) {
end_position_ = statement_pos;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Predicates. // Predicates.
...@@ -244,6 +266,9 @@ class Scope: public ZoneObject { ...@@ -244,6 +266,9 @@ class Scope: public ZoneObject {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Accessors. // Accessors.
// The type of this scope.
ScopeType type() const { return type_; }
// The variable corresponding the 'this' value. // The variable corresponding the 'this' value.
Variable* receiver() { return receiver_; } Variable* receiver() { return receiver_; }
...@@ -270,6 +295,8 @@ class Scope: public ZoneObject { ...@@ -270,6 +295,8 @@ class Scope: public ZoneObject {
// Declarations list. // Declarations list.
ZoneList<Declaration*>* declarations() { return &decls_; } ZoneList<Declaration*>* declarations() { return &decls_; }
// Inner scope list.
ZoneList<Scope*>* inner_scopes() { return &inner_scopes_; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Variable allocation. // Variable allocation.
...@@ -313,6 +340,13 @@ class Scope: public ZoneObject { ...@@ -313,6 +340,13 @@ class Scope: public ZoneObject {
Handle<SerializedScopeInfo> GetSerializedScopeInfo(); Handle<SerializedScopeInfo> GetSerializedScopeInfo();
// Get the chain of nested scopes within this scope for the source statement
// position. The scopes will be added to the list from the outermost scope to
// the innermost scope. Only nested block, catch or with scopes are tracked
// and will be returned, but no inner function scopes.
void GetNestedScopeChain(List<Handle<SerializedScopeInfo> >* chain,
int statement_position);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Strict mode support. // Strict mode support.
bool IsDeclared(Handle<String> name) { bool IsDeclared(Handle<String> name) {
...@@ -336,7 +370,7 @@ class Scope: public ZoneObject { ...@@ -336,7 +370,7 @@ class Scope: public ZoneObject {
protected: protected:
friend class ParserFactory; friend class ParserFactory;
explicit Scope(Type type); explicit Scope(ScopeType type);
Isolate* const isolate_; Isolate* const isolate_;
...@@ -345,7 +379,7 @@ class Scope: public ZoneObject { ...@@ -345,7 +379,7 @@ class Scope: public ZoneObject {
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
// The scope type. // The scope type.
Type type_; ScopeType type_;
// Debugging support. // Debugging support.
Handle<String> scope_name_; Handle<String> scope_name_;
...@@ -387,6 +421,9 @@ class Scope: public ZoneObject { ...@@ -387,6 +421,9 @@ class Scope: public ZoneObject {
bool scope_calls_eval_; bool scope_calls_eval_;
// This scope is a strict mode scope. // This scope is a strict mode scope.
bool strict_mode_; bool strict_mode_;
// Source positions.
int start_position_;
int end_position_;
// Computed via PropagateScopeInfo. // Computed via PropagateScopeInfo.
bool outer_scope_calls_non_strict_eval_; bool outer_scope_calls_non_strict_eval_;
...@@ -489,7 +526,9 @@ class Scope: public ZoneObject { ...@@ -489,7 +526,9 @@ class Scope: public ZoneObject {
private: private:
// Construct a scope based on the scope info. // Construct a scope based on the scope info.
Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info); Scope(Scope* inner_scope,
ScopeType type,
Handle<SerializedScopeInfo> scope_info);
// Construct a catch scope with a binding for the name. // Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name); Scope(Scope* inner_scope, Handle<String> catch_variable_name);
...@@ -501,7 +540,7 @@ class Scope: public ZoneObject { ...@@ -501,7 +540,7 @@ class Scope: public ZoneObject {
} }
} }
void SetDefaults(Type type, void SetDefaults(ScopeType type,
Scope* outer_scope, Scope* outer_scope,
Handle<SerializedScopeInfo> scope_info); Handle<SerializedScopeInfo> scope_info);
}; };
......
...@@ -509,6 +509,16 @@ enum CallKind { ...@@ -509,6 +509,16 @@ enum CallKind {
}; };
enum ScopeType {
EVAL_SCOPE, // The top-level scope for an eval source.
FUNCTION_SCOPE, // The top-level scope for a function.
GLOBAL_SCOPE, // The top-level scope for a program or a top-level eval.
CATCH_SCOPE, // The scope introduced by catch.
BLOCK_SCOPE, // The scope introduced by a new block.
WITH_SCOPE // The scope introduced by with.
};
static const uint32_t kHoleNanUpper32 = 0x7FFFFFFF; static const uint32_t kHoleNanUpper32 = 0x7FFFFFFF;
static const uint32_t kHoleNanLower32 = 0xFFFFFFFF; static const uint32_t kHoleNanLower32 = 0xFFFFFFFF;
static const uint32_t kNaNOrInfinityLowerBoundUpper32 = 0x7FF00000; static const uint32_t kNaNOrInfinityLowerBoundUpper32 = 0x7FF00000;
......
...@@ -744,3 +744,135 @@ TEST(RegExpScanning) { ...@@ -744,3 +744,135 @@ TEST(RegExpScanning) {
TestScanRegExp("/=/", "="); TestScanRegExp("/=/", "=");
TestScanRegExp("/=?/", "=?"); TestScanRegExp("/=?/", "=?");
} }
TEST(ScopePositions) {
// Test the parser for correctly setting the start and end positions
// of a scope. We check the scope positions of exactly one scope
// nested in the global scope of a program. 'inner source' is the
// source code that determines the part of the source belonging
// to the nested scope. 'outer_prefix' and 'outer_suffix' are
// parts of the source that belong to the global scope.
struct SourceData {
const char* outer_prefix;
const char* inner_source;
const char* outer_suffix;
i::ScopeType scope_type;
};
const SourceData source_data[] = {
{ " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE },
{ " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE },
{ " with ({}) ", "{\n"
" block;\n"
" }", "\n"
" more;", i::WITH_SCOPE },
{ " with ({}) ", "statement;", " more;", i::WITH_SCOPE },
{ " with ({}) ", "statement", "\n"
" more;", i::WITH_SCOPE },
{ " with ({})\n"
" ", "statement;", "\n"
" more;", i::WITH_SCOPE },
{ " try {} catch ", "(e) { block; }", " more;", i::CATCH_SCOPE },
{ " try {} catch ", "(e) { block; }", "; more;", i::CATCH_SCOPE },
{ " try {} catch ", "(e) {\n"
" block;\n"
" }", "\n"
" more;", i::CATCH_SCOPE },
{ " try {} catch ", "(e) { block; }", " finally { block; } more;",
i::CATCH_SCOPE },
{ " start;\n"
" ", "{ let block; }", " more;", i::BLOCK_SCOPE },
{ " start;\n"
" ", "{ let block; }", "; more;", i::BLOCK_SCOPE },
{ " start;\n"
" ", "{\n"
" let block;\n"
" }", "\n"
" more;", i::BLOCK_SCOPE },
{ " start;\n"
" function fun", "(a,b) { infunction; }", " more;",
i::FUNCTION_SCOPE },
{ " start;\n"
" function fun", "(a,b) {\n"
" infunction;\n"
" }", "\n"
" more;", i::FUNCTION_SCOPE },
{ " (function fun", "(a,b) { infunction; }", ")();",
i::FUNCTION_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
i::BLOCK_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
i::BLOCK_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x) {\n"
" block;\n"
" }", "\n"
" more;", i::BLOCK_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
i::BLOCK_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
" more;", i::BLOCK_SCOPE },
{ " for ", "(let x = 1 ; x < 10; ++ x)\n"
" statement;", "\n"
" more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {}) { block; }", " more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {}) { block; }", "; more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {}) {\n"
" block;\n"
" }", "\n"
" more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {}) statement;", " more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {}) statement", "\n"
" more;", i::BLOCK_SCOPE },
{ " for ", "(let x in {})\n"
" statement;", "\n"
" more;", i::BLOCK_SCOPE },
{ NULL, NULL, NULL, i::EVAL_SCOPE }
};
v8::HandleScope handles;
v8::Persistent<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context);
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
for (int i = 0; source_data[i].outer_prefix; i++) {
int kPrefixLen = i::StrLength(source_data[i].outer_prefix);
int kInnerLen = i::StrLength(source_data[i].inner_source);
int kSuffixLen = i::StrLength(source_data[i].outer_suffix);
int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1);
int length;
length = i::OS::SNPrintF(program, "%s%s%s",
source_data[i].outer_prefix,
source_data[i].inner_source,
source_data[i].outer_suffix);
ASSERT(length == kProgramSize);
// Parse program source.
i::Handle<i::String> source(
FACTORY->NewStringFromAscii(i::CStrVector(program.start())));
i::Handle<i::Script> script = FACTORY->NewScript(source);
i::Parser parser(script, false, NULL, NULL);
parser.SetHarmonyScoping(true);
i::FunctionLiteral* function =
parser.ParseProgram(source, true, i::kNonStrictMode);
ASSERT(function != NULL);
// Check scope types and positions.
i::Scope* scope = function->scope();
CHECK(scope->is_global_scope());
CHECK_EQ(scope->start_position(), 0);
CHECK_EQ(scope->end_position(), kProgramSize);
CHECK_EQ(scope->inner_scopes()->length(), 1);
i::Scope* inner_scope = scope->inner_scopes()->at(0);
CHECK_EQ(inner_scope->type(), source_data[i].scope_type);
CHECK_EQ(inner_scope->start_position(), kPrefixLen);
// The end position of a token is one position after the last
// character belonging to that token.
CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
}
}
// 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:
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug // Flags: --expose-debug-as debug --allow-natives-syntax
// The functions used for testing backtraces. They are at the top to make the // The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier. // testing of source line/column easier.
...@@ -439,6 +439,26 @@ with(with_object) { ...@@ -439,6 +439,26 @@ with(with_object) {
EndTest(); EndTest();
// With block in function that is marked for optimization while being executed.
BeginTest("With 7");
function with_7() {
with({}) {
%OptimizeFunctionOnNextCall(with_7);
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
};
with_7();
EndTest();
// Simple closure formed by returning an inner function referering the outer // Simple closure formed by returning an inner function referering the outer
// functions arguments. // functions arguments.
BeginTest("Closure 1"); BeginTest("Closure 1");
...@@ -950,6 +970,28 @@ try { ...@@ -950,6 +970,28 @@ try {
EndTest(); EndTest();
// Catch block in function that is marked for optimization while being executed.
BeginTest("Catch block 7");
function catch_block_7() {
%OptimizeFunctionOnNextCall(catch_block_7);
try {
throw 'Exception';
} catch (e) {
debugger;
}
};
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Catch,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({e:'Exception'}, 0, exec_state);
};
catch_block_7();
EndTest();
assertEquals(begin_test_count, break_count, assertEquals(begin_test_count, break_count,
'one or more tests did not enter the debugger'); 'one or more tests did not enter the debugger');
assertEquals(begin_test_count, end_test_count, assertEquals(begin_test_count, end_test_count,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment