Rename the toplevel code generator from "Fast" to "Full". It was
always ambiguous whether it tried to generate fast code, or generate it quickly. Review URL: http://codereview.chromium.org/549108 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3660 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
80c81d96d4
commit
6ad58b53f4
@ -428,8 +428,8 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class VirtualFrame;
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
friend class FullCodeGenerator;
|
||||
friend class FullCodeGenSyntaxChecker;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
|
||||
};
|
||||
|
@ -52,7 +52,7 @@ namespace internal {
|
||||
//
|
||||
// The function builds a JS frame. Please see JavaScriptFrameConstants in
|
||||
// frames-arm.h for its layout.
|
||||
void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
void FullCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
function_ = fun;
|
||||
SetFunctionPosition(fun);
|
||||
int locals_count = fun->scope()->num_stack_slots();
|
||||
@ -167,7 +167,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
void FullCodeGenerator::EmitReturnSequence(int position) {
|
||||
Comment cmnt(masm_, "[ Return sequence");
|
||||
if (return_label_.is_bound()) {
|
||||
__ b(&return_label_);
|
||||
@ -214,7 +214,7 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -250,7 +250,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -270,7 +270,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -290,7 +290,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
void FullCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -323,7 +323,7 @@ void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DropAndApply(int count,
|
||||
void FullCodeGenerator::DropAndApply(int count,
|
||||
Expression::Context context,
|
||||
Register reg) {
|
||||
ASSERT(count > 0);
|
||||
@ -371,7 +371,7 @@ void FastCodeGenerator::DropAndApply(int count,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context,
|
||||
void FullCodeGenerator::Apply(Expression::Context context,
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) {
|
||||
switch (context) {
|
||||
@ -432,7 +432,7 @@ void FastCodeGenerator::Apply(Expression::Context context,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
void FullCodeGenerator::DoTest(Expression::Context context) {
|
||||
// The value to test is pushed on the stack, and duplicated on the stack
|
||||
// if necessary (for value/test and test/value contexts).
|
||||
ASSERT_NE(NULL, true_label_);
|
||||
@ -495,7 +495,7 @@ void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
switch (slot->type()) {
|
||||
case Slot::PARAMETER:
|
||||
case Slot::LOCAL:
|
||||
@ -514,14 +514,14 @@ MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Register destination, Slot* source) {
|
||||
void FullCodeGenerator::Move(Register destination, Slot* source) {
|
||||
// Use destination as scratch.
|
||||
MemOperand slot_operand = EmitSlotSearch(source, destination);
|
||||
__ ldr(destination, slot_operand);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Slot* dst,
|
||||
void FullCodeGenerator::Move(Slot* dst,
|
||||
Register src,
|
||||
Register scratch1,
|
||||
Register scratch2) {
|
||||
@ -537,7 +537,7 @@ void FastCodeGenerator::Move(Slot* dst,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
Comment cmnt(masm_, "[ Declaration");
|
||||
Variable* var = decl->proxy()->var();
|
||||
ASSERT(var != NULL); // Must have been resolved.
|
||||
@ -637,7 +637,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
// The context is the first argument.
|
||||
__ mov(r1, Operand(pairs));
|
||||
@ -648,7 +648,7 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
@ -666,13 +666,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
EmitVariableLoad(expr->var(), context_);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
Expression::Context context) {
|
||||
Expression* rewrite = var->rewrite();
|
||||
if (rewrite == NULL) {
|
||||
@ -745,7 +745,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ RegExpLiteral");
|
||||
Label done;
|
||||
// Registers will be used as follows:
|
||||
@ -772,7 +772,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ObjectLiteral");
|
||||
__ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset));
|
||||
@ -847,7 +847,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
__ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
||||
@ -900,7 +900,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ mov(r2, Operand(key->handle()));
|
||||
@ -909,14 +909,14 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
__ Call(ic, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
Expression::Context context) {
|
||||
__ pop(r1);
|
||||
GenericBinaryOpStub stub(op, NO_OVERWRITE);
|
||||
@ -925,7 +925,7 @@ void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
Expression::Context context) {
|
||||
ASSERT(var != NULL);
|
||||
ASSERT(var->is_global() || var->slot() != NULL);
|
||||
@ -975,7 +975,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a named store IC.
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
ASSERT(prop != NULL);
|
||||
@ -1011,7 +1011,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// If the assignment starts a block of assignments to the same object,
|
||||
@ -1046,7 +1046,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
Expression* key = expr->key();
|
||||
|
||||
@ -1065,7 +1065,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> ignored,
|
||||
RelocInfo::Mode mode) {
|
||||
// Code common for calls using the IC.
|
||||
@ -1087,7 +1087,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
// Code common for calls using the call stub.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -1105,7 +1105,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ Call");
|
||||
Expression* fun = expr->expression();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
@ -1176,7 +1176,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
Comment cmnt(masm_, "[ CallNew");
|
||||
// According to ECMA-262, section 11.2.2, page 44, the function
|
||||
// expression in new calls must be evaluated before the
|
||||
@ -1211,7 +1211,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
|
||||
@ -1246,7 +1246,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::VOID: {
|
||||
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||
@ -1357,7 +1357,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
|
||||
// Expression can only be a property, a global or a (parameter or local)
|
||||
@ -1483,7 +1483,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Comment cmnt(masm_, "[ BinaryOperation");
|
||||
switch (expr->op()) {
|
||||
case Token::COMMA:
|
||||
@ -1518,7 +1518,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
|
||||
// Always perform the comparison for its control flow. Pack the result
|
||||
@ -1633,25 +1633,25 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
Apply(context_, r0);
|
||||
}
|
||||
|
||||
|
||||
Register FastCodeGenerator::result_register() { return r0; }
|
||||
Register FullCodeGenerator::result_register() { return r0; }
|
||||
|
||||
|
||||
Register FastCodeGenerator::context_register() { return cp; }
|
||||
Register FullCodeGenerator::context_register() { return cp; }
|
||||
|
||||
|
||||
void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
|
||||
__ str(value, MemOperand(fp, frame_offset));
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
__ ldr(dst, CodeGenerator::ContextOperand(cp, context_index));
|
||||
}
|
||||
|
||||
@ -1659,7 +1659,7 @@ void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Non-local control flow support.
|
||||
|
||||
void FastCodeGenerator::EnterFinallyBlock() {
|
||||
void FullCodeGenerator::EnterFinallyBlock() {
|
||||
ASSERT(!result_register().is(r1));
|
||||
// Store result register while executing finally block.
|
||||
__ push(result_register());
|
||||
@ -1672,7 +1672,7 @@ void FastCodeGenerator::EnterFinallyBlock() {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ExitFinallyBlock() {
|
||||
void FullCodeGenerator::ExitFinallyBlock() {
|
||||
ASSERT(!result_register().is(r1));
|
||||
// Restore result register from stack.
|
||||
__ pop(r1);
|
||||
|
458
src/compiler.cc
458
src/compiler.cc
@ -42,29 +42,6 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
class CodeGenSelector: public AstVisitor {
|
||||
public:
|
||||
enum CodeGenTag { NORMAL, FAST };
|
||||
|
||||
CodeGenSelector() : has_supported_syntax_(true) {}
|
||||
|
||||
CodeGenTag Select(FunctionLiteral* fun);
|
||||
|
||||
private:
|
||||
void VisitDeclarations(ZoneList<Declaration*>* decls);
|
||||
void VisitStatements(ZoneList<Statement*>* stmts);
|
||||
|
||||
// AST node visit functions.
|
||||
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
|
||||
bool has_supported_syntax_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
|
||||
};
|
||||
|
||||
|
||||
static Handle<Code> MakeCode(FunctionLiteral* literal,
|
||||
Handle<Script> script,
|
||||
Handle<Context> context,
|
||||
@ -117,12 +94,11 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
|
||||
!FLAG_always_fast_compiler) {
|
||||
if (FLAG_trace_bailout) PrintF("No hint to try fast\n");
|
||||
} else {
|
||||
CodeGenSelector selector;
|
||||
CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
|
||||
if (code_gen == CodeGenSelector::FAST) {
|
||||
return FastCodeGenerator::MakeCode(literal, script, is_eval);
|
||||
FullCodeGenSyntaxChecker checker;
|
||||
checker.Check(literal);
|
||||
if (checker.has_supported_syntax()) {
|
||||
return FullCodeGenerator::MakeCode(literal, script, is_eval);
|
||||
}
|
||||
ASSERT(code_gen == CodeGenSelector::NORMAL);
|
||||
}
|
||||
}
|
||||
return CodeGenerator::MakeCode(literal, script, is_eval);
|
||||
@ -494,10 +470,10 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
|
||||
// Generate code and return it.
|
||||
bool is_compiled = false;
|
||||
if (FLAG_fast_compiler && literal->try_fast_codegen()) {
|
||||
CodeGenSelector selector;
|
||||
CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
|
||||
if (code_gen == CodeGenSelector::FAST) {
|
||||
code = FastCodeGenerator::MakeCode(literal,
|
||||
FullCodeGenSyntaxChecker checker;
|
||||
checker.Check(literal);
|
||||
if (checker.has_supported_syntax()) {
|
||||
code = FullCodeGenerator::MakeCode(literal,
|
||||
script,
|
||||
false); // Not eval.
|
||||
is_compiled = true;
|
||||
@ -571,422 +547,4 @@ void Compiler::SetFunctionInfo(Handle<JSFunction> fun,
|
||||
}
|
||||
|
||||
|
||||
CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
|
||||
Scope* scope = fun->scope();
|
||||
|
||||
if (scope->num_heap_slots() > 0) {
|
||||
// We support functions with a local context if they do not have
|
||||
// parameters that need to be copied into the context.
|
||||
for (int i = 0, len = scope->num_parameters(); i < len; i++) {
|
||||
Slot* slot = scope->parameter(i)->slot();
|
||||
if (slot != NULL && slot->type() == Slot::CONTEXT) {
|
||||
if (FLAG_trace_bailout) {
|
||||
PrintF("Function has context-allocated parameters.\n");
|
||||
}
|
||||
return NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
has_supported_syntax_ = true;
|
||||
VisitDeclarations(scope->declarations());
|
||||
if (!has_supported_syntax_) return NORMAL;
|
||||
|
||||
VisitStatements(fun->body());
|
||||
return has_supported_syntax_ ? FAST : NORMAL;
|
||||
}
|
||||
|
||||
|
||||
#define BAILOUT(reason) \
|
||||
do { \
|
||||
if (FLAG_trace_bailout) { \
|
||||
PrintF("%s\n", reason); \
|
||||
} \
|
||||
has_supported_syntax_ = false; \
|
||||
return; \
|
||||
} while (false)
|
||||
|
||||
|
||||
#define CHECK_BAILOUT \
|
||||
do { \
|
||||
if (!has_supported_syntax_) return; \
|
||||
} while (false)
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) {
|
||||
for (int i = 0; i < decls->length(); i++) {
|
||||
Visit(decls->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
|
||||
for (int i = 0, len = stmts->length(); i < len; i++) {
|
||||
Visit(stmts->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDeclaration(Declaration* decl) {
|
||||
Property* prop = decl->proxy()->AsProperty();
|
||||
if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
Visit(prop->key());
|
||||
}
|
||||
|
||||
if (decl->fun() != NULL) {
|
||||
Visit(decl->fun());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitBlock(Block* stmt) {
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
|
||||
Visit(stmt->condition());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->then_statement());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->else_statement());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
BAILOUT("SwitchStatement");
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
Visit(stmt->cond());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->body());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
|
||||
Visit(stmt->cond());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->body());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitForStatement(ForStatement* stmt) {
|
||||
BAILOUT("ForStatement");
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) {
|
||||
BAILOUT("ForInStatement");
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
Visit(stmt->try_block());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->catch_block());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
Visit(stmt->try_block());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->finally_block());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitFunctionBoilerplateLiteral(
|
||||
FunctionBoilerplateLiteral* expr) {
|
||||
BAILOUT("FunctionBoilerplateLiteral");
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitConditional(Conditional* expr) {
|
||||
Visit(expr->condition());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->then_expression());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->else_expression());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitSlot(Slot* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
|
||||
Variable* var = expr->var();
|
||||
if (!var->is_global()) {
|
||||
Slot* slot = var->slot();
|
||||
if (slot != NULL) {
|
||||
Slot::Type type = slot->type();
|
||||
// When LOOKUP slots are enabled, some currently dead code
|
||||
// implementing unary typeof will become live.
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("Lookup slot");
|
||||
}
|
||||
} else {
|
||||
// If not global or a slot, it is a parameter rewritten to an explicit
|
||||
// property reference on the (shadow) arguments object.
|
||||
#ifdef DEBUG
|
||||
Property* property = var->AsProperty();
|
||||
ASSERT_NOT_NULL(property);
|
||||
Variable* object = property->obj()->AsVariableProxy()->AsVariable();
|
||||
ASSERT_NOT_NULL(object);
|
||||
ASSERT_NOT_NULL(object->slot());
|
||||
ASSERT_NOT_NULL(property->key()->AsLiteral());
|
||||
ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitLiteral(Literal* expr) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
|
||||
|
||||
for (int i = 0, len = properties->length(); i < len; i++) {
|
||||
ObjectLiteral::Property* property = properties->at(i);
|
||||
if (property->IsCompileTimeValue()) continue;
|
||||
Visit(property->key());
|
||||
CHECK_BAILOUT;
|
||||
Visit(property->value());
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
for (int i = 0, len = subexprs->length(); i < len; i++) {
|
||||
Expression* subexpr = subexprs->at(i);
|
||||
if (subexpr->AsLiteral() != NULL) continue;
|
||||
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
|
||||
Visit(subexpr);
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
Visit(expr->key());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitAssignment(Assignment* expr) {
|
||||
// We support plain non-compound assignments to properties, parameters and
|
||||
// non-context (stack-allocated) locals, and global variables.
|
||||
Token::Value op = expr->op();
|
||||
if (op == Token::INIT_CONST) BAILOUT("initialize constant");
|
||||
|
||||
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
ASSERT(var == NULL || prop == NULL);
|
||||
if (var != NULL) {
|
||||
if (var->mode() == Variable::CONST) {
|
||||
BAILOUT("Assignment to const");
|
||||
}
|
||||
// All global variables are supported.
|
||||
if (!var->is_global()) {
|
||||
ASSERT(var->slot() != NULL);
|
||||
Slot::Type type = var->slot()->type();
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("Lookup slot");
|
||||
}
|
||||
}
|
||||
} else if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// This is a throw reference error.
|
||||
BAILOUT("non-variable/non-property assignment");
|
||||
}
|
||||
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitThrow(Throw* expr) {
|
||||
Visit(expr->exception());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitProperty(Property* expr) {
|
||||
Visit(expr->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->key());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCall(Call* expr) {
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
|
||||
// Check for supported calls
|
||||
if (var != NULL && var->is_possibly_eval()) {
|
||||
BAILOUT("call to the identifier 'eval'");
|
||||
} else if (var != NULL && !var->is_this() && var->is_global()) {
|
||||
// Calls to global variables are supported.
|
||||
} else if (var != NULL && var->slot() != NULL &&
|
||||
var->slot()->type() == Slot::LOOKUP) {
|
||||
BAILOUT("call to a lookup slot");
|
||||
} else if (fun->AsProperty() != NULL) {
|
||||
Property* prop = fun->AsProperty();
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// Otherwise the call is supported if the function expression is.
|
||||
Visit(fun);
|
||||
}
|
||||
// Check all arguments to the call.
|
||||
for (int i = 0; i < args->length(); i++) {
|
||||
Visit(args->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCallNew(CallNew* expr) {
|
||||
Visit(expr->expression());
|
||||
CHECK_BAILOUT;
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
// Check all arguments to the call
|
||||
for (int i = 0; i < args->length(); i++) {
|
||||
Visit(args->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
|
||||
// Check for inline runtime call
|
||||
if (expr->name()->Get(0) == '_' &&
|
||||
CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
|
||||
BAILOUT("inlined runtime call");
|
||||
}
|
||||
// Check all arguments to the call. (Relies on TEMP meaning STACK.)
|
||||
for (int i = 0; i < expr->arguments()->length(); i++) {
|
||||
Visit(expr->arguments()->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::VOID:
|
||||
case Token::NOT:
|
||||
case Token::TYPEOF:
|
||||
Visit(expr->expression());
|
||||
break;
|
||||
case Token::BIT_NOT:
|
||||
BAILOUT("UnaryOperation: BIT_NOT");
|
||||
case Token::DELETE:
|
||||
BAILOUT("UnaryOperation: DELETE");
|
||||
case Token::ADD:
|
||||
BAILOUT("UnaryOperation: ADD");
|
||||
case Token::SUB:
|
||||
BAILOUT("UnaryOperation: SUB");
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
|
||||
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
ASSERT(var == NULL || prop == NULL);
|
||||
if (var != NULL) {
|
||||
// All global variables are supported.
|
||||
if (!var->is_global()) {
|
||||
ASSERT(var->slot() != NULL);
|
||||
Slot::Type type = var->slot()->type();
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("CountOperation with lookup slot");
|
||||
}
|
||||
}
|
||||
} else if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// This is a throw reference error.
|
||||
BAILOUT("CountOperation non-variable/non-property expression");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Visit(expr->left());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->right());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
|
||||
Visit(expr->left());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->right());
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {}
|
||||
|
||||
#undef BAILOUT
|
||||
#undef CHECK_BAILOUT
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -36,15 +36,450 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
#define BAILOUT(reason) \
|
||||
do { \
|
||||
if (FLAG_trace_bailout) { \
|
||||
PrintF("%s\n", reason); \
|
||||
} \
|
||||
has_supported_syntax_ = false; \
|
||||
return; \
|
||||
} while (false)
|
||||
|
||||
|
||||
#define CHECK_BAILOUT \
|
||||
do { \
|
||||
if (!has_supported_syntax_) return; \
|
||||
} while (false)
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
|
||||
Scope* scope = fun->scope();
|
||||
|
||||
if (scope->num_heap_slots() > 0) {
|
||||
// We support functions with a local context if they do not have
|
||||
// parameters that need to be copied into the context.
|
||||
for (int i = 0, len = scope->num_parameters(); i < len; i++) {
|
||||
Slot* slot = scope->parameter(i)->slot();
|
||||
if (slot != NULL && slot->type() == Slot::CONTEXT) {
|
||||
BAILOUT("Function has context-allocated parameters.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VisitDeclarations(scope->declarations());
|
||||
CHECK_BAILOUT;
|
||||
|
||||
VisitStatements(fun->body());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitDeclarations(
|
||||
ZoneList<Declaration*>* decls) {
|
||||
for (int i = 0; i < decls->length(); i++) {
|
||||
Visit(decls->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) {
|
||||
for (int i = 0, len = stmts->length(); i < len; i++) {
|
||||
Visit(stmts->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) {
|
||||
Property* prop = decl->proxy()->AsProperty();
|
||||
if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
Visit(prop->key());
|
||||
}
|
||||
|
||||
if (decl->fun() != NULL) {
|
||||
Visit(decl->fun());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) {
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitExpressionStatement(
|
||||
ExpressionStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) {
|
||||
Visit(stmt->condition());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->then_statement());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->else_statement());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitWithEnterStatement(
|
||||
WithEnterStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
BAILOUT("SwitchStatement");
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
Visit(stmt->cond());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->body());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) {
|
||||
Visit(stmt->cond());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->body());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) {
|
||||
BAILOUT("ForStatement");
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) {
|
||||
BAILOUT("ForInStatement");
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
Visit(stmt->try_block());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->catch_block());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitTryFinallyStatement(
|
||||
TryFinallyStatement* stmt) {
|
||||
Visit(stmt->try_block());
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmt->finally_block());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitDebuggerStatement(
|
||||
DebuggerStatement* stmt) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral(
|
||||
FunctionBoilerplateLiteral* expr) {
|
||||
BAILOUT("FunctionBoilerplateLiteral");
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) {
|
||||
Visit(expr->condition());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->then_expression());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->else_expression());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
|
||||
Variable* var = expr->var();
|
||||
if (!var->is_global()) {
|
||||
Slot* slot = var->slot();
|
||||
if (slot != NULL) {
|
||||
Slot::Type type = slot->type();
|
||||
// When LOOKUP slots are enabled, some currently dead code
|
||||
// implementing unary typeof will become live.
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("Lookup slot");
|
||||
}
|
||||
} else {
|
||||
// If not global or a slot, it is a parameter rewritten to an explicit
|
||||
// property reference on the (shadow) arguments object.
|
||||
#ifdef DEBUG
|
||||
Property* property = var->AsProperty();
|
||||
ASSERT_NOT_NULL(property);
|
||||
Variable* object = property->obj()->AsVariableProxy()->AsVariable();
|
||||
ASSERT_NOT_NULL(object);
|
||||
ASSERT_NOT_NULL(object->slot());
|
||||
ASSERT_NOT_NULL(property->key()->AsLiteral());
|
||||
ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
|
||||
|
||||
for (int i = 0, len = properties->length(); i < len; i++) {
|
||||
ObjectLiteral::Property* property = properties->at(i);
|
||||
if (property->IsCompileTimeValue()) continue;
|
||||
Visit(property->key());
|
||||
CHECK_BAILOUT;
|
||||
Visit(property->value());
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
for (int i = 0, len = subexprs->length(); i < len; i++) {
|
||||
Expression* subexpr = subexprs->at(i);
|
||||
if (subexpr->AsLiteral() != NULL) continue;
|
||||
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
|
||||
Visit(subexpr);
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCatchExtensionObject(
|
||||
CatchExtensionObject* expr) {
|
||||
Visit(expr->key());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
|
||||
// We support plain non-compound assignments to properties, parameters and
|
||||
// non-context (stack-allocated) locals, and global variables.
|
||||
Token::Value op = expr->op();
|
||||
if (op == Token::INIT_CONST) BAILOUT("initialize constant");
|
||||
|
||||
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
ASSERT(var == NULL || prop == NULL);
|
||||
if (var != NULL) {
|
||||
if (var->mode() == Variable::CONST) {
|
||||
BAILOUT("Assignment to const");
|
||||
}
|
||||
// All global variables are supported.
|
||||
if (!var->is_global()) {
|
||||
ASSERT(var->slot() != NULL);
|
||||
Slot::Type type = var->slot()->type();
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("Lookup slot");
|
||||
}
|
||||
}
|
||||
} else if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// This is a throw reference error.
|
||||
BAILOUT("non-variable/non-property assignment");
|
||||
}
|
||||
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) {
|
||||
Visit(expr->exception());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) {
|
||||
Visit(expr->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->key());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCall(Call* expr) {
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
|
||||
// Check for supported calls
|
||||
if (var != NULL && var->is_possibly_eval()) {
|
||||
BAILOUT("call to the identifier 'eval'");
|
||||
} else if (var != NULL && !var->is_this() && var->is_global()) {
|
||||
// Calls to global variables are supported.
|
||||
} else if (var != NULL && var->slot() != NULL &&
|
||||
var->slot()->type() == Slot::LOOKUP) {
|
||||
BAILOUT("call to a lookup slot");
|
||||
} else if (fun->AsProperty() != NULL) {
|
||||
Property* prop = fun->AsProperty();
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// Otherwise the call is supported if the function expression is.
|
||||
Visit(fun);
|
||||
}
|
||||
// Check all arguments to the call.
|
||||
for (int i = 0; i < args->length(); i++) {
|
||||
Visit(args->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) {
|
||||
Visit(expr->expression());
|
||||
CHECK_BAILOUT;
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
// Check all arguments to the call
|
||||
for (int i = 0; i < args->length(); i++) {
|
||||
Visit(args->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
|
||||
// Check for inline runtime call
|
||||
if (expr->name()->Get(0) == '_' &&
|
||||
CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
|
||||
BAILOUT("inlined runtime call");
|
||||
}
|
||||
// Check all arguments to the call. (Relies on TEMP meaning STACK.)
|
||||
for (int i = 0; i < expr->arguments()->length(); i++) {
|
||||
Visit(expr->arguments()->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::VOID:
|
||||
case Token::NOT:
|
||||
case Token::TYPEOF:
|
||||
Visit(expr->expression());
|
||||
break;
|
||||
case Token::BIT_NOT:
|
||||
BAILOUT("UnaryOperation: BIT_NOT");
|
||||
case Token::DELETE:
|
||||
BAILOUT("UnaryOperation: DELETE");
|
||||
case Token::ADD:
|
||||
BAILOUT("UnaryOperation: ADD");
|
||||
case Token::SUB:
|
||||
BAILOUT("UnaryOperation: SUB");
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) {
|
||||
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
ASSERT(var == NULL || prop == NULL);
|
||||
if (var != NULL) {
|
||||
// All global variables are supported.
|
||||
if (!var->is_global()) {
|
||||
ASSERT(var->slot() != NULL);
|
||||
Slot::Type type = var->slot()->type();
|
||||
if (type == Slot::LOOKUP) {
|
||||
BAILOUT("CountOperation with lookup slot");
|
||||
}
|
||||
}
|
||||
} else if (prop != NULL) {
|
||||
Visit(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
Visit(prop->key());
|
||||
CHECK_BAILOUT;
|
||||
} else {
|
||||
// This is a throw reference error.
|
||||
BAILOUT("CountOperation non-variable/non-property expression");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Visit(expr->left());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->right());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
|
||||
Visit(expr->left());
|
||||
CHECK_BAILOUT;
|
||||
Visit(expr->right());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
|
||||
// Supported.
|
||||
}
|
||||
|
||||
#undef BAILOUT
|
||||
#undef CHECK_BAILOUT
|
||||
|
||||
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
|
||||
Handle<Code> FullCodeGenerator::MakeCode(FunctionLiteral* fun,
|
||||
Handle<Script> script,
|
||||
bool is_eval) {
|
||||
CodeGenerator::MakeCodePrologue(fun);
|
||||
const int kInitialBufferSize = 4 * KB;
|
||||
MacroAssembler masm(NULL, kInitialBufferSize);
|
||||
FastCodeGenerator cgen(&masm, script, is_eval);
|
||||
FullCodeGenerator cgen(&masm, script, is_eval);
|
||||
cgen.Generate(fun);
|
||||
if (cgen.HasStackOverflow()) {
|
||||
ASSERT(!Top::has_pending_exception());
|
||||
@ -55,7 +490,7 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
|
||||
}
|
||||
|
||||
|
||||
int FastCodeGenerator::SlotOffset(Slot* slot) {
|
||||
int FullCodeGenerator::SlotOffset(Slot* slot) {
|
||||
ASSERT(slot != NULL);
|
||||
// Offset is negative because higher indexes are at lower addresses.
|
||||
int offset = -slot->index() * kPointerSize;
|
||||
@ -75,7 +510,7 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDeclarations(
|
||||
void FullCodeGenerator::VisitDeclarations(
|
||||
ZoneList<Declaration*>* declarations) {
|
||||
int length = declarations->length();
|
||||
int globals = 0;
|
||||
@ -129,42 +564,42 @@ void FastCodeGenerator::VisitDeclarations(
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
|
||||
void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
|
||||
if (FLAG_debug_info) {
|
||||
CodeGenerator::RecordPositions(masm_, fun->start_position());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
|
||||
void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
|
||||
if (FLAG_debug_info) {
|
||||
CodeGenerator::RecordPositions(masm_, fun->end_position());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetStatementPosition(Statement* stmt) {
|
||||
void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
|
||||
if (FLAG_debug_info) {
|
||||
CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetStatementPosition(int pos) {
|
||||
void FullCodeGenerator::SetStatementPosition(int pos) {
|
||||
if (FLAG_debug_info) {
|
||||
CodeGenerator::RecordPositions(masm_, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetSourcePosition(int pos) {
|
||||
void FullCodeGenerator::SetSourcePosition(int pos) {
|
||||
if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
|
||||
masm_->RecordPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
|
||||
void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
|
||||
Label eval_right, done;
|
||||
|
||||
// Set up the appropriate context for the left subexpression based
|
||||
@ -232,7 +667,7 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
void FullCodeGenerator::VisitBlock(Block* stmt) {
|
||||
Comment cmnt(masm_, "[ Block");
|
||||
Breakable nested_statement(this, stmt);
|
||||
SetStatementPosition(stmt);
|
||||
@ -241,20 +676,20 @@ void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ExpressionStatement");
|
||||
SetStatementPosition(stmt);
|
||||
VisitForEffect(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ EmptyStatement");
|
||||
SetStatementPosition(stmt);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
||||
void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ IfStatement");
|
||||
SetStatementPosition(stmt);
|
||||
Label then_part, else_part, done;
|
||||
@ -273,7 +708,7 @@ void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ContinueStatement");
|
||||
SetStatementPosition(stmt);
|
||||
NestedStatement* current = nesting_stack_;
|
||||
@ -289,7 +724,7 @@ void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
||||
void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ BreakStatement");
|
||||
SetStatementPosition(stmt);
|
||||
NestedStatement* current = nesting_stack_;
|
||||
@ -305,7 +740,7 @@ void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ReturnStatement");
|
||||
SetStatementPosition(stmt);
|
||||
Expression* expr = stmt->expression();
|
||||
@ -324,7 +759,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
||||
void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ WithEnterStatement");
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
@ -342,7 +777,7 @@ void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
|
||||
void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ WithExitStatement");
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
@ -353,12 +788,12 @@ void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ DoWhileStatement");
|
||||
SetStatementPosition(stmt);
|
||||
Label body, stack_limit_hit, stack_check_success;
|
||||
@ -388,7 +823,7 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ WhileStatement");
|
||||
SetStatementPosition(stmt);
|
||||
Label body, stack_limit_hit, stack_check_success;
|
||||
@ -419,17 +854,17 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ TryCatchStatement");
|
||||
SetStatementPosition(stmt);
|
||||
// The try block adds a handler to the exception handler chain
|
||||
@ -472,7 +907,7 @@ void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ TryFinallyStatement");
|
||||
SetStatementPosition(stmt);
|
||||
// Try finally is compiled by setting up a try-handler on the stack while
|
||||
@ -536,7 +971,7 @@ void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
||||
void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
Comment cmnt(masm_, "[ DebuggerStatement");
|
||||
SetStatementPosition(stmt);
|
||||
@ -546,13 +981,13 @@ void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionBoilerplateLiteral(
|
||||
void FullCodeGenerator::VisitFunctionBoilerplateLiteral(
|
||||
FunctionBoilerplateLiteral* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitConditional(Conditional* expr) {
|
||||
void FullCodeGenerator::VisitConditional(Conditional* expr) {
|
||||
Comment cmnt(masm_, "[ Conditional");
|
||||
Label true_case, false_case, done;
|
||||
VisitForControl(expr->condition(), &true_case, &false_case);
|
||||
@ -573,19 +1008,19 @@ void FastCodeGenerator::VisitConditional(Conditional* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitSlot(Slot* expr) {
|
||||
void FullCodeGenerator::VisitSlot(Slot* expr) {
|
||||
// Slots do not appear directly in the AST.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitLiteral(Literal* expr) {
|
||||
void FullCodeGenerator::VisitLiteral(Literal* expr) {
|
||||
Comment cmnt(masm_, "[ Literal");
|
||||
Apply(context_, expr);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
// Left-hand side can only be a property, a global or a (parameter or local)
|
||||
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
|
||||
@ -664,7 +1099,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
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");
|
||||
@ -676,7 +1111,7 @@ void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitThrow(Throw* expr) {
|
||||
void FullCodeGenerator::VisitThrow(Throw* expr) {
|
||||
Comment cmnt(masm_, "[ Throw");
|
||||
VisitForValue(expr->exception(), kStack);
|
||||
__ CallRuntime(Runtime::kThrow, 1);
|
||||
@ -684,7 +1119,7 @@ void FastCodeGenerator::VisitThrow(Throw* expr) {
|
||||
}
|
||||
|
||||
|
||||
int FastCodeGenerator::TryFinally::Exit(int stack_depth) {
|
||||
int FullCodeGenerator::TryFinally::Exit(int stack_depth) {
|
||||
// The macros used here must preserve the result register.
|
||||
__ Drop(stack_depth);
|
||||
__ PopTryHandler();
|
||||
@ -693,7 +1128,7 @@ int FastCodeGenerator::TryFinally::Exit(int stack_depth) {
|
||||
}
|
||||
|
||||
|
||||
int FastCodeGenerator::TryCatch::Exit(int stack_depth) {
|
||||
int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
|
||||
// The macros used here must preserve the result register.
|
||||
__ Drop(stack_depth);
|
||||
__ PopTryHandler();
|
||||
|
@ -35,12 +35,35 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Fast code generator.
|
||||
|
||||
class FastCodeGenerator: public AstVisitor {
|
||||
class FullCodeGenSyntaxChecker: public AstVisitor {
|
||||
public:
|
||||
FastCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
|
||||
FullCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
|
||||
|
||||
void Check(FunctionLiteral* fun);
|
||||
|
||||
bool has_supported_syntax() { return has_supported_syntax_; }
|
||||
|
||||
private:
|
||||
void VisitDeclarations(ZoneList<Declaration*>* decls);
|
||||
void VisitStatements(ZoneList<Statement*>* stmts);
|
||||
|
||||
// AST node visit functions.
|
||||
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
|
||||
bool has_supported_syntax_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FullCodeGenSyntaxChecker);
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Full code generator.
|
||||
|
||||
class FullCodeGenerator: public AstVisitor {
|
||||
public:
|
||||
FullCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
|
||||
: masm_(masm),
|
||||
function_(NULL),
|
||||
script_(script),
|
||||
@ -68,7 +91,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
|
||||
class NestedStatement BASE_EMBEDDED {
|
||||
public:
|
||||
explicit NestedStatement(FastCodeGenerator* codegen) : codegen_(codegen) {
|
||||
explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
|
||||
// Link into codegen's nesting stack.
|
||||
previous_ = codegen->nesting_stack_;
|
||||
codegen->nesting_stack_ = this;
|
||||
@ -106,14 +129,14 @@ class FastCodeGenerator: public AstVisitor {
|
||||
protected:
|
||||
MacroAssembler* masm() { return codegen_->masm(); }
|
||||
private:
|
||||
FastCodeGenerator* codegen_;
|
||||
FullCodeGenerator* codegen_;
|
||||
NestedStatement* previous_;
|
||||
DISALLOW_COPY_AND_ASSIGN(NestedStatement);
|
||||
};
|
||||
|
||||
class Breakable : public NestedStatement {
|
||||
public:
|
||||
Breakable(FastCodeGenerator* codegen,
|
||||
Breakable(FullCodeGenerator* codegen,
|
||||
BreakableStatement* break_target)
|
||||
: NestedStatement(codegen),
|
||||
target_(break_target) {}
|
||||
@ -132,7 +155,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
|
||||
class Iteration : public Breakable {
|
||||
public:
|
||||
Iteration(FastCodeGenerator* codegen,
|
||||
Iteration(FullCodeGenerator* codegen,
|
||||
IterationStatement* iteration_statement)
|
||||
: Breakable(codegen, iteration_statement) {}
|
||||
virtual ~Iteration() {}
|
||||
@ -149,7 +172,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
// The environment inside the try block of a try/catch statement.
|
||||
class TryCatch : public NestedStatement {
|
||||
public:
|
||||
explicit TryCatch(FastCodeGenerator* codegen, Label* catch_entry)
|
||||
explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
|
||||
: NestedStatement(codegen), catch_entry_(catch_entry) { }
|
||||
virtual ~TryCatch() {}
|
||||
virtual TryCatch* AsTryCatch() { return this; }
|
||||
@ -163,7 +186,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
// The environment inside the try block of a try/finally statement.
|
||||
class TryFinally : public NestedStatement {
|
||||
public:
|
||||
explicit TryFinally(FastCodeGenerator* codegen, Label* finally_entry)
|
||||
explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
|
||||
: NestedStatement(codegen), finally_entry_(finally_entry) { }
|
||||
virtual ~TryFinally() {}
|
||||
virtual TryFinally* AsTryFinally() { return this; }
|
||||
@ -179,7 +202,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
// the block's parameters from the stack.
|
||||
class Finally : public NestedStatement {
|
||||
public:
|
||||
explicit Finally(FastCodeGenerator* codegen) : NestedStatement(codegen) { }
|
||||
explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
|
||||
virtual ~Finally() {}
|
||||
virtual Finally* AsFinally() { return this; }
|
||||
virtual int Exit(int stack_depth) {
|
||||
@ -196,7 +219,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
// the block's temporary storage from the stack.
|
||||
class ForIn : public Iteration {
|
||||
public:
|
||||
ForIn(FastCodeGenerator* codegen,
|
||||
ForIn(FullCodeGenerator* codegen,
|
||||
ForInStatement* statement)
|
||||
: Iteration(codegen, statement) { }
|
||||
virtual ~ForIn() {}
|
||||
@ -410,7 +433,7 @@ class FastCodeGenerator: public AstVisitor {
|
||||
|
||||
friend class NestedStatement;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
|
||||
DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
|
||||
};
|
||||
|
||||
|
||||
|
@ -614,8 +614,8 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
friend class Result;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
friend class FullCodeGenerator;
|
||||
friend class FullCodeGenSyntaxChecker;
|
||||
|
||||
friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace internal {
|
||||
//
|
||||
// The function builds a JS frame. Please see JavaScriptFrameConstants in
|
||||
// frames-ia32.h for its layout.
|
||||
void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
void FullCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
function_ = fun;
|
||||
SetFunctionPosition(fun);
|
||||
|
||||
@ -160,7 +160,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
void FullCodeGenerator::EmitReturnSequence(int position) {
|
||||
Comment cmnt(masm_, "[ Return sequence");
|
||||
if (return_label_.is_bound()) {
|
||||
__ jmp(&return_label_);
|
||||
@ -193,7 +193,7 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -236,7 +236,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -279,7 +279,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -320,7 +320,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
void FullCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -361,7 +361,7 @@ void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DropAndApply(int count,
|
||||
void FullCodeGenerator::DropAndApply(int count,
|
||||
Expression::Context context,
|
||||
Register reg) {
|
||||
ASSERT(count > 0);
|
||||
@ -413,7 +413,7 @@ void FastCodeGenerator::DropAndApply(int count,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context,
|
||||
void FullCodeGenerator::Apply(Expression::Context context,
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) {
|
||||
switch (context) {
|
||||
@ -478,7 +478,7 @@ void FastCodeGenerator::Apply(Expression::Context context,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
void FullCodeGenerator::DoTest(Expression::Context context) {
|
||||
// The value to test is in the accumulator. If the value might be needed
|
||||
// on the stack (value/test and test/value contexts with a stack location
|
||||
// desired), then the value is already duplicated on the stack.
|
||||
@ -612,7 +612,7 @@ void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
switch (slot->type()) {
|
||||
case Slot::PARAMETER:
|
||||
case Slot::LOCAL:
|
||||
@ -631,13 +631,13 @@ MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Register destination, Slot* source) {
|
||||
void FullCodeGenerator::Move(Register destination, Slot* source) {
|
||||
MemOperand location = EmitSlotSearch(source, destination);
|
||||
__ mov(destination, location);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Slot* dst,
|
||||
void FullCodeGenerator::Move(Slot* dst,
|
||||
Register src,
|
||||
Register scratch1,
|
||||
Register scratch2) {
|
||||
@ -653,7 +653,7 @@ void FastCodeGenerator::Move(Slot* dst,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
Comment cmnt(masm_, "[ Declaration");
|
||||
Variable* var = decl->proxy()->var();
|
||||
ASSERT(var != NULL); // Must have been resolved.
|
||||
@ -751,7 +751,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
__ push(esi); // The context is the first argument.
|
||||
__ push(Immediate(pairs));
|
||||
@ -761,7 +761,7 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
@ -779,13 +779,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
EmitVariableLoad(expr->var(), context_);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
Expression::Context context) {
|
||||
Expression* rewrite = var->rewrite();
|
||||
if (rewrite == NULL) {
|
||||
@ -862,7 +862,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ RegExpLiteral");
|
||||
Label done;
|
||||
// Registers will be used as follows:
|
||||
@ -889,7 +889,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ObjectLiteral");
|
||||
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
|
||||
@ -958,7 +958,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
|
||||
@ -1008,7 +1008,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ mov(ecx, Immediate(key->handle()));
|
||||
@ -1018,7 +1018,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
@ -1026,7 +1026,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
Expression::Context context) {
|
||||
__ push(result_register());
|
||||
GenericBinaryOpStub stub(op,
|
||||
@ -1037,7 +1037,7 @@ void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
Expression::Context context) {
|
||||
ASSERT(var != NULL);
|
||||
ASSERT(var->is_global() || var->slot() != NULL);
|
||||
@ -1086,7 +1086,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a named store IC.
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
ASSERT(prop != NULL);
|
||||
@ -1121,7 +1121,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// If the assignment starts a block of assignments to the same object,
|
||||
@ -1157,7 +1157,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
Expression* key = expr->key();
|
||||
|
||||
@ -1177,7 +1177,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> name,
|
||||
RelocInfo::Mode mode) {
|
||||
// Code common for calls using the IC.
|
||||
@ -1198,7 +1198,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
// Code common for calls using the call stub.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -1215,7 +1215,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ Call");
|
||||
Expression* fun = expr->expression();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
@ -1286,7 +1286,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
Comment cmnt(masm_, "[ CallNew");
|
||||
// According to ECMA-262, section 11.2.2, page 44, the function
|
||||
// expression in new calls must be evaluated before the
|
||||
@ -1321,7 +1321,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
|
||||
@ -1353,7 +1353,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::VOID: {
|
||||
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||
@ -1463,7 +1463,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
|
||||
// Expression can only be a property, a global or a (parameter or local)
|
||||
@ -1595,7 +1595,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Comment cmnt(masm_, "[ BinaryOperation");
|
||||
switch (expr->op()) {
|
||||
case Token::COMMA:
|
||||
@ -1630,7 +1630,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
|
||||
// Always perform the comparison for its control flow. Pack the result
|
||||
@ -1745,25 +1745,25 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
Apply(context_, eax);
|
||||
}
|
||||
|
||||
|
||||
Register FastCodeGenerator::result_register() { return eax; }
|
||||
Register FullCodeGenerator::result_register() { return eax; }
|
||||
|
||||
|
||||
Register FastCodeGenerator::context_register() { return esi; }
|
||||
Register FullCodeGenerator::context_register() { return esi; }
|
||||
|
||||
|
||||
void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
|
||||
__ mov(Operand(ebp, frame_offset), value);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
__ mov(dst, CodeGenerator::ContextOperand(esi, context_index));
|
||||
}
|
||||
|
||||
@ -1771,7 +1771,7 @@ void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Non-local control flow support.
|
||||
|
||||
void FastCodeGenerator::EnterFinallyBlock() {
|
||||
void FullCodeGenerator::EnterFinallyBlock() {
|
||||
// Cook return address on top of stack (smi encoded Code* delta)
|
||||
ASSERT(!result_register().is(edx));
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
@ -1785,7 +1785,7 @@ void FastCodeGenerator::EnterFinallyBlock() {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ExitFinallyBlock() {
|
||||
void FullCodeGenerator::ExitFinallyBlock() {
|
||||
ASSERT(!result_register().is(edx));
|
||||
// Restore result register from stack.
|
||||
__ pop(result_register());
|
||||
|
@ -611,8 +611,8 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
friend class Result;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
friend class FullCodeGenerator;
|
||||
friend class FullCodeGenSyntaxChecker;
|
||||
|
||||
friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace internal {
|
||||
//
|
||||
// The function builds a JS frame. Please see JavaScriptFrameConstants in
|
||||
// frames-x64.h for its layout.
|
||||
void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
void FullCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
function_ = fun;
|
||||
SetFunctionPosition(fun);
|
||||
|
||||
@ -161,7 +161,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
void FullCodeGenerator::EmitReturnSequence(int position) {
|
||||
Comment cmnt(masm_, "[ Return sequence");
|
||||
if (return_label_.is_bound()) {
|
||||
__ jmp(&return_label_);
|
||||
@ -200,7 +200,7 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -243,7 +243,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -285,7 +285,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -324,7 +324,7 @@ void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
void FullCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
switch (context) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
@ -364,7 +364,7 @@ void FastCodeGenerator::ApplyTOS(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DropAndApply(int count,
|
||||
void FullCodeGenerator::DropAndApply(int count,
|
||||
Expression::Context context,
|
||||
Register reg) {
|
||||
ASSERT(count > 0);
|
||||
@ -415,7 +415,7 @@ void FastCodeGenerator::DropAndApply(int count,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Apply(Expression::Context context,
|
||||
void FullCodeGenerator::Apply(Expression::Context context,
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) {
|
||||
switch (context) {
|
||||
@ -480,7 +480,7 @@ void FastCodeGenerator::Apply(Expression::Context context,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
void FullCodeGenerator::DoTest(Expression::Context context) {
|
||||
// The value to test is in the accumulator. If the value might be needed
|
||||
// on the stack (value/test and test/value contexts with a stack location
|
||||
// desired), then the value is already duplicated on the stack.
|
||||
@ -614,7 +614,7 @@ void FastCodeGenerator::DoTest(Expression::Context context) {
|
||||
}
|
||||
|
||||
|
||||
MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
switch (slot->type()) {
|
||||
case Slot::PARAMETER:
|
||||
case Slot::LOCAL:
|
||||
@ -633,13 +633,13 @@ MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Register destination, Slot* source) {
|
||||
void FullCodeGenerator::Move(Register destination, Slot* source) {
|
||||
MemOperand location = EmitSlotSearch(source, destination);
|
||||
__ movq(destination, location);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::Move(Slot* dst,
|
||||
void FullCodeGenerator::Move(Slot* dst,
|
||||
Register src,
|
||||
Register scratch1,
|
||||
Register scratch2) {
|
||||
@ -655,7 +655,7 @@ void FastCodeGenerator::Move(Slot* dst,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
Comment cmnt(masm_, "[ Declaration");
|
||||
Variable* var = decl->proxy()->var();
|
||||
ASSERT(var != NULL); // Must have been resolved.
|
||||
@ -754,7 +754,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
__ push(rsi); // The context is the first argument.
|
||||
__ Push(pairs);
|
||||
@ -764,7 +764,7 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
@ -782,13 +782,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
EmitVariableLoad(expr->var(), context_);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
Expression::Context context) {
|
||||
Expression* rewrite = var->rewrite();
|
||||
if (rewrite == NULL) {
|
||||
@ -864,7 +864,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ RegExpLiteral");
|
||||
Label done;
|
||||
// Registers will be used as follows:
|
||||
@ -890,7 +890,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ObjectLiteral");
|
||||
__ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
|
||||
@ -960,7 +960,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
__ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
|
||||
@ -1010,7 +1010,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ Move(rcx, key->handle());
|
||||
@ -1020,7 +1020,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
__ Call(ic, RelocInfo::CODE_TARGET);
|
||||
@ -1028,7 +1028,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
Expression::Context context) {
|
||||
__ push(result_register());
|
||||
GenericBinaryOpStub stub(op,
|
||||
@ -1039,7 +1039,7 @@ void FastCodeGenerator::EmitBinaryOp(Token::Value op,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
Expression::Context context) {
|
||||
ASSERT(var != NULL);
|
||||
ASSERT(var->is_global() || var->slot() != NULL);
|
||||
@ -1086,7 +1086,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a named store IC.
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
ASSERT(prop != NULL);
|
||||
@ -1121,7 +1121,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// If the assignment starts a block of assignments to the same object,
|
||||
@ -1157,7 +1157,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
Expression* key = expr->key();
|
||||
|
||||
@ -1177,7 +1177,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> ignored,
|
||||
RelocInfo::Mode mode) {
|
||||
// Code common for calls using the IC.
|
||||
@ -1200,7 +1200,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
// Code common for calls using the call stub.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -1218,7 +1218,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ Call");
|
||||
Expression* fun = expr->expression();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
@ -1292,7 +1292,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
Comment cmnt(masm_, "[ CallNew");
|
||||
// According to ECMA-262, section 11.2.2, page 44, the function
|
||||
// expression in new calls must be evaluated before the
|
||||
@ -1327,7 +1327,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
|
||||
@ -1360,7 +1360,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::VOID: {
|
||||
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||
@ -1470,7 +1470,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
|
||||
// Expression can only be a property, a global or a (parameter or local)
|
||||
@ -1601,7 +1601,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Comment cmnt(masm_, "[ BinaryOperation");
|
||||
switch (expr->op()) {
|
||||
case Token::COMMA:
|
||||
@ -1636,7 +1636,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
|
||||
// Always perform the comparison for its control flow. Pack the result
|
||||
@ -1748,25 +1748,25 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
__ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
Apply(context_, rax);
|
||||
}
|
||||
|
||||
|
||||
Register FastCodeGenerator::result_register() { return rax; }
|
||||
Register FullCodeGenerator::result_register() { return rax; }
|
||||
|
||||
|
||||
Register FastCodeGenerator::context_register() { return rsi; }
|
||||
Register FullCodeGenerator::context_register() { return rsi; }
|
||||
|
||||
|
||||
void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
|
||||
ASSERT(IsAligned(frame_offset, kPointerSize));
|
||||
__ movq(Operand(rbp, frame_offset), value);
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
__ movq(dst, CodeGenerator::ContextOperand(rsi, context_index));
|
||||
}
|
||||
|
||||
@ -1775,7 +1775,7 @@ void FastCodeGenerator::LoadContextField(Register dst, int context_index) {
|
||||
// Non-local control flow support.
|
||||
|
||||
|
||||
void FastCodeGenerator::EnterFinallyBlock() {
|
||||
void FullCodeGenerator::EnterFinallyBlock() {
|
||||
ASSERT(!result_register().is(rdx));
|
||||
ASSERT(!result_register().is(rcx));
|
||||
// Cook return address on top of stack (smi encoded Code* delta)
|
||||
@ -1789,7 +1789,7 @@ void FastCodeGenerator::EnterFinallyBlock() {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::ExitFinallyBlock() {
|
||||
void FullCodeGenerator::ExitFinallyBlock() {
|
||||
ASSERT(!result_register().is(rdx));
|
||||
ASSERT(!result_register().is(rcx));
|
||||
// Restore result register from stack.
|
||||
|
Loading…
Reference in New Issue
Block a user