Stop using with explicitly to implement try/catch.
The AST for TryCatch gives us enough structure that we do not need to expand it to explicitly include a with. Try/catch is still handled the same as before at runtime. R=ager@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/7134014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8224 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
699d17c3b9
commit
e9a1ffde92
@ -298,6 +298,12 @@ void MacroAssembler::Call(Label* target) {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::Push(Handle<Object> handle) {
|
||||
mov(ip, Operand(handle));
|
||||
push(ip);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::Move(Register dst, Handle<Object> value) {
|
||||
mov(dst, Operand(value));
|
||||
}
|
||||
|
@ -192,6 +192,9 @@ class MacroAssembler: public Assembler {
|
||||
Register address,
|
||||
Register scratch);
|
||||
|
||||
// Push a handle.
|
||||
void Push(Handle<Object> handle);
|
||||
|
||||
// Push two registers. Pushes leftmost register first (to highest address).
|
||||
void Push(Register src1, Register src2, Condition cond = al) {
|
||||
ASSERT(!src1.is(src2));
|
||||
|
11
src/ast.cc
11
src/ast.cc
@ -293,11 +293,11 @@ void ObjectLiteral::CalculateEmitStore() {
|
||||
|
||||
void TargetCollector::AddTarget(Label* target) {
|
||||
// Add the label to the collector, but discard duplicates.
|
||||
int length = targets_->length();
|
||||
int length = targets_.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (targets_->at(i) == target) return;
|
||||
if (targets_[i] == target) return;
|
||||
}
|
||||
targets_->Add(target);
|
||||
targets_.Add(target);
|
||||
}
|
||||
|
||||
|
||||
@ -392,11 +392,6 @@ bool TryFinallyStatement::IsInlineable() const {
|
||||
}
|
||||
|
||||
|
||||
bool CatchExtensionObject::IsInlineable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DebuggerStatement::IsInlineable() const {
|
||||
return false;
|
||||
}
|
||||
|
46
src/ast.h
46
src/ast.h
@ -80,7 +80,6 @@ namespace internal {
|
||||
V(RegExpLiteral) \
|
||||
V(ObjectLiteral) \
|
||||
V(ArrayLiteral) \
|
||||
V(CatchExtensionObject) \
|
||||
V(Assignment) \
|
||||
V(Throw) \
|
||||
V(Property) \
|
||||
@ -614,19 +613,17 @@ class ReturnStatement: public Statement {
|
||||
|
||||
class WithEnterStatement: public Statement {
|
||||
public:
|
||||
explicit WithEnterStatement(Expression* expression, bool is_catch_block)
|
||||
: expression_(expression), is_catch_block_(is_catch_block) { }
|
||||
explicit WithEnterStatement(Expression* expression)
|
||||
: expression_(expression) { }
|
||||
|
||||
DECLARE_NODE_TYPE(WithEnterStatement)
|
||||
|
||||
Expression* expression() const { return expression_; }
|
||||
|
||||
bool is_catch_block() const { return is_catch_block_; }
|
||||
virtual bool IsInlineable() const;
|
||||
|
||||
private:
|
||||
Expression* expression_;
|
||||
bool is_catch_block_;
|
||||
};
|
||||
|
||||
|
||||
@ -743,9 +740,7 @@ class IfStatement: public Statement {
|
||||
// stack in the compiler; this should probably be reworked.
|
||||
class TargetCollector: public AstNode {
|
||||
public:
|
||||
explicit TargetCollector(ZoneList<Label*>* targets)
|
||||
: targets_(targets) {
|
||||
}
|
||||
TargetCollector(): targets_(0) { }
|
||||
|
||||
// Adds a jump target to the collector. The collector stores a pointer not
|
||||
// a copy of the target to make binding work, so make sure not to pass in
|
||||
@ -756,11 +751,11 @@ class TargetCollector: public AstNode {
|
||||
virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
|
||||
virtual TargetCollector* AsTargetCollector() { return this; }
|
||||
|
||||
ZoneList<Label*>* targets() { return targets_; }
|
||||
ZoneList<Label*>* targets() { return &targets_; }
|
||||
virtual bool IsInlineable() const;
|
||||
|
||||
private:
|
||||
ZoneList<Label*>* targets_;
|
||||
ZoneList<Label*> targets_;
|
||||
};
|
||||
|
||||
|
||||
@ -785,22 +780,20 @@ class TryStatement: public Statement {
|
||||
|
||||
class TryCatchStatement: public TryStatement {
|
||||
public:
|
||||
TryCatchStatement(Block* try_block,
|
||||
VariableProxy* catch_var,
|
||||
Block* catch_block)
|
||||
TryCatchStatement(Block* try_block, Handle<String> name, Block* catch_block)
|
||||
: TryStatement(try_block),
|
||||
catch_var_(catch_var),
|
||||
name_(name),
|
||||
catch_block_(catch_block) {
|
||||
}
|
||||
|
||||
DECLARE_NODE_TYPE(TryCatchStatement)
|
||||
|
||||
VariableProxy* catch_var() const { return catch_var_; }
|
||||
Block* catch_block() const { return catch_block_; }
|
||||
Handle<String> name() const { return name_; }
|
||||
virtual bool IsInlineable() const;
|
||||
|
||||
private:
|
||||
VariableProxy* catch_var_;
|
||||
Handle<String> name_;
|
||||
Block* catch_block_;
|
||||
};
|
||||
|
||||
@ -1040,27 +1033,6 @@ class ArrayLiteral: public MaterializedLiteral {
|
||||
};
|
||||
|
||||
|
||||
// Node for constructing a context extension object for a catch block.
|
||||
// The catch context extension object has one property, the catch
|
||||
// variable, which should be DontDelete.
|
||||
class CatchExtensionObject: public Expression {
|
||||
public:
|
||||
CatchExtensionObject(Literal* key, VariableProxy* value)
|
||||
: key_(key), value_(value) {
|
||||
}
|
||||
|
||||
DECLARE_NODE_TYPE(CatchExtensionObject)
|
||||
|
||||
Literal* key() const { return key_; }
|
||||
VariableProxy* value() const { return value_; }
|
||||
virtual bool IsInlineable() const;
|
||||
|
||||
private:
|
||||
Literal* key_;
|
||||
VariableProxy* value_;
|
||||
};
|
||||
|
||||
|
||||
class VariableProxy: public Expression {
|
||||
public:
|
||||
explicit VariableProxy(Variable* var);
|
||||
|
@ -187,11 +187,6 @@ void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCatchExtensionObject(
|
||||
CatchExtensionObject* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
|
||||
// If assigning to a property (including a global property) the assignment is
|
||||
// breakable.
|
||||
@ -962,15 +957,7 @@ void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
VisitForStackValue(stmt->expression());
|
||||
if (stmt->is_catch_block()) {
|
||||
__ CallRuntime(Runtime::kPushCatchContext, 1);
|
||||
} else {
|
||||
__ CallRuntime(Runtime::kPushContext, 1);
|
||||
}
|
||||
// Both runtime calls return the new context in both the context and the
|
||||
// result registers.
|
||||
|
||||
// Update local stack frame context field.
|
||||
__ CallRuntime(Runtime::kPushContext, 1);
|
||||
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
|
||||
}
|
||||
|
||||
@ -1117,15 +1104,15 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
__ Call(&try_handler_setup);
|
||||
// Try handler code, exception in result register.
|
||||
|
||||
// Store exception in local .catch variable before executing catch block.
|
||||
{
|
||||
// The catch variable is *always* a variable proxy for a local variable.
|
||||
Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable();
|
||||
ASSERT_NOT_NULL(catch_var);
|
||||
Slot* variable_slot = catch_var->AsSlot();
|
||||
ASSERT_NOT_NULL(variable_slot);
|
||||
ASSERT_EQ(Slot::LOCAL, variable_slot->type());
|
||||
StoreToFrameField(SlotOffset(variable_slot), result_register());
|
||||
// Extend the context before executing the catch block.
|
||||
{ Comment cmnt(masm_, "[ Extend catch context");
|
||||
__ Push(stmt->name());
|
||||
__ push(result_register());
|
||||
__ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
|
||||
__ push(result_register());
|
||||
__ CallRuntime(Runtime::kPushCatchContext, 1);
|
||||
StoreToFrameField(StandardFrameConstants::kContextOffset,
|
||||
context_register());
|
||||
}
|
||||
|
||||
Visit(stmt->catch_block());
|
||||
@ -1281,18 +1268,6 @@ void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
// Call runtime routine to allocate the catch extension object and
|
||||
// assign the exception value to the catch variable.
|
||||
Comment cmnt(masm_, "[ CatchExtensionObject");
|
||||
VisitForStackValue(expr->key());
|
||||
VisitForStackValue(expr->value());
|
||||
// Create catch extension object.
|
||||
__ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
|
||||
context()->Plug(result_register());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitThrow(Throw* expr) {
|
||||
Comment cmnt(masm_, "[ Throw");
|
||||
VisitForStackValue(expr->exception());
|
||||
|
@ -3187,14 +3187,6 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
ASSERT(!HasStackOverflow());
|
||||
ASSERT(current_block() != NULL);
|
||||
ASSERT(current_block()->HasPredecessor());
|
||||
return Bailout("CatchExtensionObject");
|
||||
}
|
||||
|
||||
|
||||
// Sets the lookup result and returns true if the store can be inlined.
|
||||
static bool ComputeStoredField(Handle<Map> type,
|
||||
Handle<String> name,
|
||||
|
@ -449,6 +449,13 @@ void Assembler::push(const Operand& src) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::push(Handle<Object> handle) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x68);
|
||||
emit(handle);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::pop(Register dst) {
|
||||
ASSERT(reloc_info_writer.last_pc() != NULL);
|
||||
EnsureSpace ensure_space(this);
|
||||
|
@ -659,6 +659,7 @@ class Assembler : public AssemblerBase {
|
||||
void push_imm32(int32_t imm32);
|
||||
void push(Register src);
|
||||
void push(const Operand& src);
|
||||
void push(Handle<Object> handle);
|
||||
|
||||
void pop(Register dst);
|
||||
void pop(const Operand& dst);
|
||||
|
@ -591,6 +591,9 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
void Move(Register target, Handle<Object> value);
|
||||
|
||||
// Push a handle value.
|
||||
void Push(Handle<Object> handle) { push(handle); }
|
||||
|
||||
Handle<Object> CodeObject() {
|
||||
ASSERT(!code_object_.is_null());
|
||||
return code_object_;
|
||||
|
@ -1906,13 +1906,9 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
||||
}
|
||||
|
||||
|
||||
Block* Parser::WithHelper(Expression* obj,
|
||||
ZoneStringList* labels,
|
||||
bool is_catch_block,
|
||||
bool* ok) {
|
||||
Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
|
||||
// Parse the statement and collect escaping labels.
|
||||
ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0);
|
||||
TargetCollector collector(target_list);
|
||||
TargetCollector collector;
|
||||
Statement* stat;
|
||||
{ Target target(&this->target_stack_, &collector);
|
||||
with_nesting_level_++;
|
||||
@ -1926,7 +1922,7 @@ Block* Parser::WithHelper(Expression* obj,
|
||||
Block* result = new(zone()) Block(NULL, 2, false);
|
||||
|
||||
if (result != NULL) {
|
||||
result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block));
|
||||
result->AddStatement(new(zone()) WithEnterStatement(obj));
|
||||
|
||||
// Create body block.
|
||||
Block* body = new(zone()) Block(NULL, 1, false);
|
||||
@ -1961,7 +1957,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
||||
Expression* expr = ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
return WithHelper(expr, labels, false, CHECK_OK);
|
||||
return WithHelper(expr, labels, CHECK_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -2057,18 +2053,13 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
|
||||
Expect(Token::TRY, CHECK_OK);
|
||||
|
||||
ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0);
|
||||
TargetCollector collector(target_list);
|
||||
TargetCollector try_collector;
|
||||
Block* try_block;
|
||||
|
||||
{ Target target(&this->target_stack_, &collector);
|
||||
{ Target target(&this->target_stack_, &try_collector);
|
||||
try_block = ParseBlock(NULL, CHECK_OK);
|
||||
}
|
||||
|
||||
Block* catch_block = NULL;
|
||||
Variable* catch_var = NULL;
|
||||
Block* finally_block = NULL;
|
||||
|
||||
Token::Value tok = peek();
|
||||
if (tok != Token::CATCH && tok != Token::FINALLY) {
|
||||
ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
|
||||
@ -2077,18 +2068,17 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
}
|
||||
|
||||
// If we can break out from the catch block and there is a finally block,
|
||||
// then we will need to collect jump targets from the catch block. Since
|
||||
// we don't know yet if there will be a finally block, we always collect
|
||||
// the jump targets.
|
||||
ZoneList<Label*>* catch_target_list = new(zone()) ZoneList<Label*>(0);
|
||||
TargetCollector catch_collector(catch_target_list);
|
||||
bool has_catch = false;
|
||||
// then we will need to collect escaping targets from the catch
|
||||
// block. Since we don't know yet if there will be a finally block, we
|
||||
// always collect the targets.
|
||||
TargetCollector catch_collector;
|
||||
Block* catch_block = NULL;
|
||||
Handle<String> name;
|
||||
if (tok == Token::CATCH) {
|
||||
has_catch = true;
|
||||
Consume(Token::CATCH);
|
||||
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||
name = ParseIdentifier(CHECK_OK);
|
||||
|
||||
if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
|
||||
ReportMessage("strict_catch_variable", Vector<const char*>::empty());
|
||||
@ -2099,17 +2089,33 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
if (peek() == Token::LBRACE) {
|
||||
// Allocate a temporary for holding the finally state while
|
||||
// executing the finally block.
|
||||
catch_var =
|
||||
top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol());
|
||||
Literal* name_literal = new(zone()) Literal(name);
|
||||
VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var);
|
||||
Expression* obj =
|
||||
new(zone()) CatchExtensionObject(name_literal, catch_var_use);
|
||||
// Rewrite the catch body B to a single statement block
|
||||
// { try B finally { PopContext }}.
|
||||
Block* inner_body;
|
||||
// We need to collect escapes from the body for both the inner
|
||||
// try/finally used to pop the catch context and any possible outer
|
||||
// try/finally.
|
||||
TargetCollector inner_collector;
|
||||
{ Target target(&this->target_stack_, &catch_collector);
|
||||
catch_block = WithHelper(obj, NULL, true, CHECK_OK);
|
||||
{ Target target(&this->target_stack_, &inner_collector);
|
||||
++with_nesting_level_;
|
||||
top_scope_->RecordWithStatement();
|
||||
inner_body = ParseBlock(NULL, CHECK_OK);
|
||||
--with_nesting_level_;
|
||||
}
|
||||
}
|
||||
|
||||
// Create exit block.
|
||||
Block* inner_finally = new(zone()) Block(NULL, 1, false);
|
||||
inner_finally->AddStatement(new(zone()) WithExitStatement());
|
||||
|
||||
// Create a try/finally statement.
|
||||
TryFinallyStatement* inner_try_finally =
|
||||
new(zone()) TryFinallyStatement(inner_body, inner_finally);
|
||||
inner_try_finally->set_escaping_targets(inner_collector.targets());
|
||||
|
||||
catch_block = new (zone()) Block(NULL, 1, false);
|
||||
catch_block->AddStatement(inner_try_finally);
|
||||
} else {
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
}
|
||||
@ -2117,23 +2123,21 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
tok = peek();
|
||||
}
|
||||
|
||||
if (tok == Token::FINALLY || !has_catch) {
|
||||
Block* finally_block = NULL;
|
||||
if (tok == Token::FINALLY || catch_block == NULL) {
|
||||
Consume(Token::FINALLY);
|
||||
// Declare a variable for holding the finally state while
|
||||
// executing the finally block.
|
||||
finally_block = ParseBlock(NULL, CHECK_OK);
|
||||
}
|
||||
|
||||
// Simplify the AST nodes by converting:
|
||||
// 'try { } catch { } finally { }'
|
||||
// 'try B0 catch B1 finally B2'
|
||||
// to:
|
||||
// 'try { try { } catch { } } finally { }'
|
||||
// 'try { try B0 catch B1 } finally B2'
|
||||
|
||||
if (catch_block != NULL && finally_block != NULL) {
|
||||
VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
|
||||
TryCatchStatement* statement =
|
||||
new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
|
||||
statement->set_escaping_targets(collector.targets());
|
||||
new(zone()) TryCatchStatement(try_block, name, catch_block);
|
||||
statement->set_escaping_targets(try_collector.targets());
|
||||
try_block = new(zone()) Block(NULL, 1, false);
|
||||
try_block->AddStatement(statement);
|
||||
catch_block = NULL;
|
||||
@ -2142,20 +2146,16 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
TryStatement* result = NULL;
|
||||
if (catch_block != NULL) {
|
||||
ASSERT(finally_block == NULL);
|
||||
VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
|
||||
result =
|
||||
new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
|
||||
result->set_escaping_targets(collector.targets());
|
||||
new(zone()) TryCatchStatement(try_block, name, catch_block);
|
||||
} else {
|
||||
ASSERT(finally_block != NULL);
|
||||
result = new(zone()) TryFinallyStatement(try_block, finally_block);
|
||||
// Add the jump targets of the try block and the catch block.
|
||||
for (int i = 0; i < collector.targets()->length(); i++) {
|
||||
catch_collector.AddTarget(collector.targets()->at(i));
|
||||
}
|
||||
result->set_escaping_targets(catch_collector.targets());
|
||||
// Combine the jump targets of the try block and the possible catch block.
|
||||
try_collector.targets()->AddAll(*catch_collector.targets());
|
||||
}
|
||||
|
||||
result->set_escaping_targets(try_collector.targets());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -498,10 +498,7 @@ class Parser {
|
||||
Statement* ParseContinueStatement(bool* ok);
|
||||
Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
|
||||
Statement* ParseReturnStatement(bool* ok);
|
||||
Block* WithHelper(Expression* obj,
|
||||
ZoneStringList* labels,
|
||||
bool is_catch_block,
|
||||
bool* ok);
|
||||
Block* WithHelper(Expression* obj, ZoneStringList* labels, bool* ok);
|
||||
Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
|
||||
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
|
||||
SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -201,7 +201,8 @@ void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
|
||||
Print("try ");
|
||||
Visit(node->try_block());
|
||||
Print(" catch (");
|
||||
Visit(node->catch_var());
|
||||
const bool quote = false;
|
||||
PrintLiteral(node->name(), quote);
|
||||
Print(") ");
|
||||
Visit(node->catch_block());
|
||||
}
|
||||
@ -282,15 +283,6 @@ void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
}
|
||||
|
||||
|
||||
void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
|
||||
Print("{ ");
|
||||
Visit(node->key());
|
||||
Print(": ");
|
||||
Visit(node->value());
|
||||
Print(" }");
|
||||
}
|
||||
|
||||
|
||||
void PrettyPrinter::VisitSlot(Slot* node) {
|
||||
switch (node->type()) {
|
||||
case Slot::PARAMETER:
|
||||
@ -862,7 +854,8 @@ void AstPrinter::VisitForInStatement(ForInStatement* node) {
|
||||
void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
|
||||
IndentedScope indent(this, "TRY CATCH");
|
||||
PrintIndentedVisit("TRY", node->try_block());
|
||||
PrintIndentedVisit("CATCHVAR", node->catch_var());
|
||||
const bool quote = false;
|
||||
PrintLiteralIndented("CATCHVAR", node->name(), quote);
|
||||
PrintIndentedVisit("CATCH", node->catch_block());
|
||||
}
|
||||
|
||||
@ -962,13 +955,6 @@ void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
}
|
||||
|
||||
|
||||
void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
|
||||
IndentedScope indent(this, "CatchExtensionObject");
|
||||
PrintIndentedVisit("KEY", node->key());
|
||||
PrintIndentedVisit("VALUE", node->value());
|
||||
}
|
||||
|
||||
|
||||
void AstPrinter::VisitSlot(Slot* node) {
|
||||
PrintIndented("SLOT ");
|
||||
PrettyPrinter::VisitSlot(node);
|
||||
@ -1254,8 +1240,10 @@ void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
TagScope tag(this, "TryCatchStatement");
|
||||
{ AttributesScope attributes(this);
|
||||
AddAttribute("variable", stmt->name());
|
||||
}
|
||||
Visit(stmt->try_block());
|
||||
Visit(stmt->catch_var());
|
||||
Visit(stmt->catch_block());
|
||||
}
|
||||
|
||||
@ -1360,13 +1348,6 @@ void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
TagScope tag(this, "CatchExtensionObject");
|
||||
Visit(expr->key());
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void JsonAstBuilder::VisitAssignment(Assignment* expr) {
|
||||
TagScope tag(this, "Assignment");
|
||||
{
|
||||
|
@ -252,12 +252,6 @@ void Processor::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
}
|
||||
|
||||
|
||||
void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) {
|
||||
USE(node);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void Processor::VisitAssignment(Assignment* node) {
|
||||
USE(node);
|
||||
UNREACHABLE();
|
||||
|
@ -640,6 +640,7 @@ class Assembler : public AssemblerBase {
|
||||
void push_imm32(int32_t imm32);
|
||||
void push(Register src);
|
||||
void push(const Operand& src);
|
||||
void push(Handle<Object> handle);
|
||||
|
||||
void pop(Register dst);
|
||||
void pop(const Operand& dst);
|
||||
|
Loading…
Reference in New Issue
Block a user