Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: src/runtime.cc

Issue 7523027: Provisional implementation of stack allocated catch variables. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/rewriter.cc ('k') | src/scopeinfo.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index df225b63f3fcc66734c27563908ee261584cd2ad..694c87234bb7aea2e88cf211de664a097bf8a948 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10219,11 +10219,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2);
// Fill in the values of the locals.
+ int first_stack_index = info.first_stack_index();
int i = 0;
for (; i < info.number_of_stack_slots(); ++i) {
// Use the value from the stack.
locals->set(i * 2, *info.LocalName(i));
- locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
+ locals->set(i * 2 + 1,
+ frame_inspector.GetExpression(i + first_stack_index));
}
if (i < info.NumberOfLocals()) {
// Get the context containing declarations.
@@ -10456,12 +10458,14 @@ static Handle<JSObject> MaterializeLocalScope(
}
// Second fill all stack locals.
+ int first_stack_index = scope_info.first_stack_index();
for (int i = 0; i < scope_info.number_of_stack_slots(); ++i) {
+ int index = i + first_stack_index;
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
SetProperty(local_scope,
scope_info.stack_slot_name(i),
- Handle<Object>(frame_inspector.GetExpression(i)),
+ Handle<Object>(frame_inspector.GetExpression(index)),
NONE,
kNonStrictMode),
Handle<JSObject>());
@@ -10568,6 +10572,88 @@ static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
}
+
+// Create a plain JSObject which materializes the local scope for the specified
+// frame.
+static Handle<JSObject> MaterializeLocalScope(
+ Isolate* isolate,
+ Handle<Context> context,
+ Handle<SerializedScopeInfo> serialized_scope_info,
+ JavaScriptFrame* frame,
+ int inlined_frame_index) {
+ Handle<JSFunction> function(JSFunction::cast(frame->function()));
+ ScopeInfo<> scope_info(*serialized_scope_info);
+ FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
+
+ // Allocate and initialize a JSObject with all the arguments, stack locals
+ // heap locals and extension properties of the debugged function.
+ Handle<JSObject> local_scope =
+ isolate->factory()->NewJSObject(isolate->object_function());
+
+ // First fill all parameters.
+ for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
+ RETURN_IF_EMPTY_HANDLE_VALUE(
+ isolate,
+ SetProperty(local_scope,
+ scope_info.parameter_name(i),
+ Handle<Object>(frame_inspector.GetParameter(i)),
+ NONE,
+ kNonStrictMode),
+ Handle<JSObject>());
+ }
+
+ // Second fill all stack locals.
+ int first_stack_index = scope_info.first_stack_index();
+ for (int i = 0; i < scope_info.number_of_stack_slots(); ++i) {
+ int index = i + first_stack_index;
+ RETURN_IF_EMPTY_HANDLE_VALUE(
+ isolate,
+ SetProperty(local_scope,
+ scope_info.stack_slot_name(i),
+ Handle<Object>(frame_inspector.GetExpression(index)),
+ NONE,
+ kNonStrictMode),
+ Handle<JSObject>());
+ }
+
+ if (scope_info.number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
+ // Third fill all context locals.
+ Handle<Context> frame_context(Context::cast(frame->context()));
+ Handle<Context> function_context(frame_context->declaration_context());
+ if (!CopyContextLocalsToScopeObject(isolate,
+ serialized_scope_info, scope_info,
+ function_context, local_scope)) {
+ return Handle<JSObject>();
+ }
+
+ // Finally copy any properties from the function context extension.
+ // These will be variables introduced by eval.
+ if (function_context->closure() == *function) {
+ if (function_context->has_extension() &&
+ !function_context->IsGlobalContext()) {
+ Handle<JSObject> ext(JSObject::cast(function_context->extension()));
+ Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
+ for (int i = 0; i < keys->length(); i++) {
+ // Names of variables introduced by eval are strings.
+ ASSERT(keys->get(i)->IsString());
+ Handle<String> key(String::cast(keys->get(i)));
+ RETURN_IF_EMPTY_HANDLE_VALUE(
+ isolate,
+ SetProperty(local_scope,
+ key,
+ GetProperty(ext, key),
+ NONE,
+ kNonStrictMode),
+ Handle<JSObject>());
+ }
+ }
+ }
+ }
+
+ return local_scope;
+}
+
+
// Iterate over the actual scopes visible from a stack frame. All scopes are
// backed by an actual context except the local scope, which is inserted
// "artifically" in the context chain.
@@ -10589,66 +10675,74 @@ class ScopeIterator {
inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())),
- local_done_(false),
- at_local_(false) {
+ local_scope_chain_(4) {
- // Check whether the first scope is actually a local scope.
- if (context_->IsGlobalContext()) {
- // If there is a stack slot for .result then this local scope has been
- // created for evaluating top level code and it is not a real local scope.
- // 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()->
- StackSlotIndex(isolate_->heap()->result_symbol());
- at_local_ = index < 0;
- } else if (context_->IsFunctionContext()) {
- at_local_ = true;
- } else if (context_->closure() != *function_) {
- // The context_ is a with or catch block from the outer function.
- ASSERT(context_->IsWithContext() || context_->IsCatchContext());
- at_local_ = true;
- }
+ Handle<SerializedScopeInfo> scope_info(function_->shared()->scope_info());
+ int statement_position =
+ function_->code()->SourceStatementPosition(frame_->pc());
+ scope_info->GetLocalScopeChain(&local_scope_chain_, statement_position);
+
+ if (!local_scope_chain_.is_empty()) return;
}
// More scopes?
bool Done() { return context_.is_null(); }
- // Move to the next scope.
- void Next() {
- // If at a local scope mark the local scope as passed.
- if (at_local_) {
- at_local_ = false;
- local_done_ = true;
-
- // If the current context is not associated with the local scope the
- // current context is the next real scope, so don't move to the next
- // context in this case.
- if (context_->closure() != *function_) {
- return;
- }
- }
-
+ private:
+ void AdvanceContext() {
// The global scope is always the last in the chain.
if (context_->IsGlobalContext()) {
context_ = Handle<Context>();
return;
}
-
- // Move to the next context.
context_ = Handle<Context>(context_->previous(), isolate_);
+ }
- // If passing the local scope indicate that the current scope is now the
- // local scope.
- if (!local_done_ &&
- (context_->IsGlobalContext() || context_->IsFunctionContext())) {
- at_local_ = true;
+ public:
+ // Move to the next scope.
+ void Next() {
+ // Move to the next scope.
+ if (local_scope_chain_.is_empty()) {
+ AdvanceContext();
+ } else {
+ if (local_scope_chain_.last()->HasContext()) {
+ AdvanceContext();
+ }
+ local_scope_chain_.RemoveLast();
}
}
// Return the type of the current scope.
int Type() {
- if (at_local_) {
- return ScopeTypeLocal;
+ if (!local_scope_chain_.is_empty()) {
+ Handle<SerializedScopeInfo> scope_info = local_scope_chain_.last();
+ if (scope_info->ScopeType() == Scope::FUNCTION_SCOPE) {
+ // If there is a stack slot for .result then this local scope has been
+ // created for evaluating top level code and it is not a real local
+ // scope. 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 =
+ scope_info->StackSlotIndex(isolate_->heap()->result_symbol());
+ if (index >= 0) {
+ ASSERT(context_->IsGlobalContext());
+ return ScopeTypeGlobal;
+ }
+ ASSERT(context_->IsFunctionContext() ||
+ !scope_info->HasContext());
+ return ScopeTypeLocal;
+ } else if (scope_info->ScopeType() == Scope::GLOBAL_SCOPE) {
+ ASSERT(context_->IsGlobalContext());
+ return ScopeTypeGlobal;
+ } else if (scope_info->ScopeType() == Scope::CATCH_SCOPE) {
+ ASSERT(context_->IsCatchContext() ||
+ !scope_info->HasContext());
+ return ScopeTypeCatch;
+ } else {
+ ASSERT(scope_info->ScopeType() == Scope::WITH_SCOPE);
+ ASSERT(context_->IsWithContext());
+ return ScopeTypeWith;
+ }
}
if (context_->IsGlobalContext()) {
ASSERT(context_->global()->IsGlobalObject());
@@ -10668,15 +10762,31 @@ class ScopeIterator {
Handle<JSObject> ScopeObject() {
switch (Type()) {
case ScopeIterator::ScopeTypeGlobal:
+ if (CurrentContext().is_null()) {
+ return Handle<JSObject>();
+ }
return Handle<JSObject>(CurrentContext()->global());
case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject.
- return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
+ ASSERT(local_scope_chain_.length() == 1);
+ return MaterializeLocalScope(isolate_,
+ CurrentContext(),
+ local_scope_chain_.last(),
+ frame_,
+ inlined_frame_index_);
case ScopeIterator::ScopeTypeWith:
// Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
case ScopeIterator::ScopeTypeCatch:
- return MaterializeCatchScope(isolate_, CurrentContext());
+ if (local_scope_chain_.is_empty()) {
+ return MaterializeCatchScope(isolate_, CurrentContext());
+ } else {
+ return MaterializeLocalScope(isolate_,
+ CurrentContext(),
+ local_scope_chain_.last(),
+ frame_,
+ inlined_frame_index_);
+ }
case ScopeIterator::ScopeTypeClosure:
// Materialize the content of the closure scope into a JSObject.
return MaterializeClosure(isolate_, CurrentContext());
@@ -10688,10 +10798,14 @@ class ScopeIterator {
// Return the context for this scope. For the local context there might not
// be an actual context.
Handle<Context> CurrentContext() {
- if (at_local_ && context_->closure() != *function_) {
+ if (Type() == ScopeTypeGlobal ||
+ local_scope_chain_.is_empty()) {
+ return context_;
+ } else if (local_scope_chain_.last()->HasContext()) {
+ return context_;
+ } else {
return Handle<Context>();
}
- return context_;
}
#ifdef DEBUG
@@ -10754,8 +10868,7 @@ class ScopeIterator {
int inlined_frame_index_;
Handle<JSFunction> function_;
Handle<Context> context_;
- bool local_done_;
- bool at_local_;
+ List<Handle<SerializedScopeInfo> > local_scope_chain_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
};
« no previous file with comments | « src/rewriter.cc ('k') | src/scopeinfo.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698