summaryrefslogtreecommitdiff
path: root/deps/v8/src/full-codegen/full-codegen.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/full-codegen/full-codegen.h')
-rw-r--r--deps/v8/src/full-codegen/full-codegen.h136
1 files changed, 95 insertions, 41 deletions
diff --git a/deps/v8/src/full-codegen/full-codegen.h b/deps/v8/src/full-codegen/full-codegen.h
index 52eddafa1a..6ab02313bb 100644
--- a/deps/v8/src/full-codegen/full-codegen.h
+++ b/deps/v8/src/full-codegen/full-codegen.h
@@ -42,6 +42,7 @@ class FullCodeGenerator: public AstVisitor {
nesting_stack_(NULL),
loop_depth_(0),
try_catch_depth_(0),
+ operand_stack_depth_(0),
globals_(NULL),
context_(NULL),
bailout_entries_(info->HasDeoptimizationSupport()
@@ -96,9 +97,12 @@ class FullCodeGenerator: public AstVisitor {
#error Unsupported target architecture.
#endif
+ static Register result_register();
+
private:
class Breakable;
class Iteration;
+ class TryFinally;
class TestContext;
@@ -115,11 +119,13 @@ class FullCodeGenerator: public AstVisitor {
codegen_->nesting_stack_ = previous_;
}
- virtual Breakable* AsBreakable() { return NULL; }
- virtual Iteration* AsIteration() { return NULL; }
+ virtual Breakable* AsBreakable() { return nullptr; }
+ virtual Iteration* AsIteration() { return nullptr; }
+ virtual TryFinally* AsTryFinally() { return nullptr; }
virtual bool IsContinueTarget(Statement* target) { return false; }
virtual bool IsBreakTarget(Statement* target) { return false; }
+ virtual bool IsTryFinally() { return false; }
// Notify the statement that we are exiting it via break, continue, or
// return and give it a chance to generate cleanup code. Return the
@@ -131,11 +137,6 @@ class FullCodeGenerator: public AstVisitor {
return previous_;
}
- // Like the Exit() method above, but limited to accumulating stack depth.
- virtual NestedStatement* AccumulateDepth(int* stack_depth) {
- return previous_;
- }
-
protected:
MacroAssembler* masm() { return codegen_->masm(); }
@@ -211,10 +212,43 @@ class FullCodeGenerator: public AstVisitor {
*stack_depth += kElementCount;
return previous_;
}
- NestedStatement* AccumulateDepth(int* stack_depth) override {
- *stack_depth += kElementCount;
- return previous_;
- }
+ };
+
+ class DeferredCommands {
+ public:
+ enum Command { kReturn, kThrow, kBreak, kContinue };
+ typedef int TokenId;
+ struct DeferredCommand {
+ Command command;
+ TokenId token;
+ Statement* target;
+ };
+
+ DeferredCommands(FullCodeGenerator* codegen, Label* finally_entry)
+ : codegen_(codegen),
+ commands_(codegen->zone()),
+ return_token_(TokenDispenserForFinally::kInvalidToken),
+ throw_token_(TokenDispenserForFinally::kInvalidToken),
+ finally_entry_(finally_entry) {}
+
+ void EmitCommands();
+
+ void RecordBreak(Statement* target);
+ void RecordContinue(Statement* target);
+ void RecordReturn();
+ void RecordThrow();
+ void EmitFallThrough();
+
+ private:
+ MacroAssembler* masm() { return codegen_->masm(); }
+ void EmitJumpToFinally(TokenId token);
+
+ FullCodeGenerator* codegen_;
+ ZoneVector<DeferredCommand> commands_;
+ TokenDispenserForFinally dispenser_;
+ TokenId return_token_;
+ TokenId throw_token_;
+ Label* finally_entry_;
};
// The try block of a try/finally statement.
@@ -222,18 +256,18 @@ class FullCodeGenerator: public AstVisitor {
public:
static const int kElementCount = TryBlockConstant::kElementCount;
- TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
- : NestedStatement(codegen), finally_entry_(finally_entry) {
- }
+ TryFinally(FullCodeGenerator* codegen, DeferredCommands* commands)
+ : NestedStatement(codegen), deferred_commands_(commands) {}
NestedStatement* Exit(int* stack_depth, int* context_length) override;
- NestedStatement* AccumulateDepth(int* stack_depth) override {
- *stack_depth += kElementCount;
- return previous_;
- }
+
+ bool IsTryFinally() override { return true; }
+ TryFinally* AsTryFinally() override { return this; }
+
+ DeferredCommands* deferred_commands() { return deferred_commands_; }
private:
- Label* finally_entry_;
+ DeferredCommands* deferred_commands_;
};
// The finally block of a try/finally statement.
@@ -247,10 +281,6 @@ class FullCodeGenerator: public AstVisitor {
*stack_depth += kElementCount;
return previous_;
}
- NestedStatement* AccumulateDepth(int* stack_depth) override {
- *stack_depth += kElementCount;
- return previous_;
- }
};
// The body of a for/in loop.
@@ -266,10 +296,6 @@ class FullCodeGenerator: public AstVisitor {
*stack_depth += kElementCount;
return previous_;
}
- NestedStatement* AccumulateDepth(int* stack_depth) override {
- *stack_depth += kElementCount;
- return previous_;
- }
};
@@ -354,18 +380,21 @@ class FullCodeGenerator: public AstVisitor {
MemOperand VarOperand(Variable* var, Register scratch);
void VisitForEffect(Expression* expr) {
+ if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
EffectContext context(this);
Visit(expr);
PrepareForBailout(expr, NO_REGISTERS);
}
void VisitForAccumulatorValue(Expression* expr) {
+ if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
AccumulatorValueContext context(this);
Visit(expr);
PrepareForBailout(expr, TOS_REG);
}
void VisitForStackValue(Expression* expr) {
+ if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
StackValueContext context(this);
Visit(expr);
PrepareForBailout(expr, NO_REGISTERS);
@@ -375,6 +404,7 @@ class FullCodeGenerator: public AstVisitor {
Label* if_true,
Label* if_false,
Label* fall_through) {
+ if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
TestContext context(this, expr, if_true, if_false, fall_through);
Visit(expr);
// For test contexts, we prepare for bailout before branching, not at
@@ -389,6 +419,34 @@ class FullCodeGenerator: public AstVisitor {
void DeclareGlobals(Handle<FixedArray> pairs);
int DeclareGlobalsFlags();
+ // Push, pop or drop values onto/from the operand stack.
+ void PushOperand(Register reg);
+ void PopOperand(Register reg);
+ void DropOperands(int count);
+
+ // Convenience helpers for pushing onto the operand stack.
+ void PushOperand(MemOperand operand);
+ void PushOperand(Handle<Object> handle);
+ void PushOperand(Smi* smi);
+
+ // Convenience helpers for pushing/popping multiple operands.
+ void PushOperands(Register reg1, Register reg2);
+ void PushOperands(Register reg1, Register reg2, Register reg3);
+ void PushOperands(Register reg1, Register reg2, Register reg3, Register reg4);
+ void PopOperands(Register reg1, Register reg2);
+
+ // Convenience helper for calling a runtime function that consumes arguments
+ // from the operand stack (only usable for functions with known arity).
+ void CallRuntimeWithOperands(Runtime::FunctionId function_id);
+
+ // Static tracking of the operand stack depth.
+ void OperandStackDepthDecrement(int count);
+ void OperandStackDepthIncrement(int count);
+
+ // Generate debug code that verifies that our static tracking of the operand
+ // stack depth is in sync with the actual operand stack during runtime.
+ void EmitOperandStackDepthCheck();
+
// Generate code to create an iterator result object. The "value" property is
// set to a value popped from the stack, and "done" is set according to the
// argument. The result object is left in the result register.
@@ -455,11 +513,13 @@ class FullCodeGenerator: public AstVisitor {
// Emit code to pop values from the stack associated with nested statements
// like try/catch, try/finally, etc, running the finallies and unwinding the
- // handlers as needed.
- void EmitUnwindBeforeReturn();
+ // handlers as needed. Also emits the return sequence if necessary (i.e.,
+ // if the return is not delayed by a finally block).
+ void EmitUnwindAndReturn();
// Platform-specific return sequence
void EmitReturnSequence();
+ void EmitProfilingCounterHandlingForReturnSequence(bool is_tail_call);
// Platform-specific code sequences for calls
void EmitCall(Call* expr, ConvertReceiverMode = ConvertReceiverMode::kAny);
@@ -477,26 +537,18 @@ class FullCodeGenerator: public AstVisitor {
F(IsRegExp) \
F(IsJSProxy) \
F(Call) \
- F(ArgumentsLength) \
- F(Arguments) \
F(ValueOf) \
- F(SetValueOf) \
- F(IsDate) \
F(StringCharFromCode) \
F(StringCharAt) \
F(OneByteSeqStringSetChar) \
F(TwoByteSeqStringSetChar) \
- F(ObjectEquals) \
- F(IsFunction) \
F(IsJSReceiver) \
- F(IsSimdValue) \
F(MathPow) \
- F(IsMinusZero) \
F(HasCachedArrayIndex) \
F(GetCachedArrayIndex) \
F(GetSuperConstructor) \
- F(FastOneByteArrayJoin) \
F(GeneratorNext) \
+ F(GeneratorReturn) \
F(GeneratorThrow) \
F(DebugBreakInOptimizedCode) \
F(ClassOf) \
@@ -633,7 +685,7 @@ class FullCodeGenerator: public AstVisitor {
TypeFeedbackId id = TypeFeedbackId::None());
// Inside typeof reference errors are never thrown.
- void CallLoadIC(TypeofMode typeof_mode, LanguageMode language_mode = SLOPPY,
+ void CallLoadIC(TypeofMode typeof_mode,
TypeFeedbackId id = TypeFeedbackId::None());
void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
@@ -669,6 +721,9 @@ class FullCodeGenerator: public AstVisitor {
void ExitFinallyBlock();
void ClearPendingMessage();
+ void EmitContinue(Statement* target);
+ void EmitBreak(Statement* target);
+
// Loop nesting counter.
int loop_depth() { return loop_depth_; }
void increment_loop_depth() { loop_depth_++; }
@@ -693,7 +748,6 @@ class FullCodeGenerator: public AstVisitor {
FunctionLiteral* literal() const { return info_->literal(); }
Scope* scope() { return scope_; }
- static Register result_register();
static Register context_register();
// Set fields in the stack frame. Offsets are the frame pointer relative
@@ -945,6 +999,7 @@ class FullCodeGenerator: public AstVisitor {
NestedStatement* nesting_stack_;
int loop_depth_;
int try_catch_depth_;
+ int operand_stack_depth_;
ZoneList<Handle<Object> >* globals_;
Handle<FixedArray> modules_;
int module_index_;
@@ -954,7 +1009,6 @@ class FullCodeGenerator: public AstVisitor {
ZoneVector<HandlerTableEntry> handler_table_;
int ic_total_count_;
Handle<Cell> profiling_counter_;
- bool generate_debug_code_;
friend class NestedStatement;