| Index: src/hydrogen.h
|
| diff --git a/src/hydrogen.h b/src/hydrogen.h
|
| index a8c3c5f73b28f5a3ecb82262731667e0ad7ced59..809942b065560773789a131804cb10452090bd61 100644
|
| --- a/src/hydrogen.h
|
| +++ b/src/hydrogen.h
|
| @@ -125,7 +125,12 @@ class HBasicBlock: public ZoneObject {
|
|
|
| void Finish(HControlInstruction* last);
|
| void FinishExit(HControlInstruction* instruction);
|
| - void Goto(HBasicBlock* block, FunctionState* state = NULL);
|
| + void Goto(HBasicBlock* block,
|
| + FunctionState* state = NULL,
|
| + bool add_simulate = true);
|
| + void GotoNoSimulate(HBasicBlock* block) {
|
| + Goto(block, NULL, false);
|
| + }
|
|
|
| int PredecessorIndexOf(HBasicBlock* predecessor) const;
|
| void AddSimulate(BailoutId ast_id,
|
| @@ -675,6 +680,9 @@ enum ArgumentsAllowedFlag {
|
| ARGUMENTS_ALLOWED
|
| };
|
|
|
| +
|
| +class HIfContinuation;
|
| +
|
| // This class is not BASE_EMBEDDED because our inlining implementation uses
|
| // new and delete.
|
| class AstContext {
|
| @@ -700,6 +708,13 @@ class AstContext {
|
| // expressions.
|
| virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
|
|
|
| + // Finishes the current basic block and materialize a boolean for
|
| + // value context, nothing for effect, generate a branch for test context.
|
| + // Call this function in tail position in the Visit functions for
|
| + // expressions that use an IfBuilder.
|
| + virtual void ReturnContinuation(HIfContinuation* continuation,
|
| + BailoutId ast_id) = 0;
|
| +
|
| void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
|
| bool is_for_typeof() { return for_typeof_; }
|
|
|
| @@ -735,6 +750,8 @@ class EffectContext: public AstContext {
|
| virtual void ReturnValue(HValue* value);
|
| virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
|
| virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
|
| + virtual void ReturnContinuation(HIfContinuation* continuation,
|
| + BailoutId ast_id);
|
| };
|
|
|
|
|
| @@ -748,6 +765,8 @@ class ValueContext: public AstContext {
|
| virtual void ReturnValue(HValue* value);
|
| virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
|
| virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
|
| + virtual void ReturnContinuation(HIfContinuation* continuation,
|
| + BailoutId ast_id);
|
|
|
| bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
|
|
|
| @@ -773,6 +792,8 @@ class TestContext: public AstContext {
|
| virtual void ReturnValue(HValue* value);
|
| virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
|
| virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
|
| + virtual void ReturnContinuation(HIfContinuation* continuation,
|
| + BailoutId ast_id);
|
|
|
| static TestContext* cast(AstContext* context) {
|
| ASSERT(context->IsTest());
|
| @@ -860,6 +881,45 @@ class FunctionState {
|
| };
|
|
|
|
|
| +class HIfContinuation {
|
| + public:
|
| + HIfContinuation() { continuation_captured_ = false; }
|
| + ~HIfContinuation() { ASSERT(!continuation_captured_); }
|
| +
|
| + void Capture(HBasicBlock* true_branch,
|
| + HBasicBlock* false_branch,
|
| + int position) {
|
| + ASSERT(!continuation_captured_);
|
| + ASSERT(true_branch != NULL || false_branch != NULL);
|
| + true_branch_ = true_branch;
|
| + false_branch_ = false_branch;
|
| + position_ = position;
|
| + continuation_captured_ = true;
|
| + }
|
| +
|
| + void Continue(HBasicBlock** true_branch,
|
| + HBasicBlock** false_branch,
|
| + int* position) {
|
| + ASSERT(continuation_captured_);
|
| + *true_branch = true_branch_;
|
| + *false_branch = false_branch_;
|
| + if (position != NULL) *position = position_;
|
| + continuation_captured_ = false;
|
| + }
|
| +
|
| + bool IsTrueReachable() { return true_branch_ != NULL; }
|
| + bool IsFalseReachable() { return false_branch_ != NULL; }
|
| + bool TrueAndFalseReachable() {
|
| + return IsTrueReachable() || IsFalseReachable();
|
| + }
|
| +
|
| + bool continuation_captured_;
|
| + HBasicBlock* true_branch_;
|
| + HBasicBlock* false_branch_;
|
| + int position_;
|
| +};
|
| +
|
| +
|
| class HGraphBuilder {
|
| public:
|
| explicit HGraphBuilder(CompilationInfo* info)
|
| @@ -903,9 +963,12 @@ class HGraphBuilder {
|
| protected:
|
| virtual bool BuildGraph() = 0;
|
|
|
| - HBasicBlock* CreateBasicBlock(HEnvironment* envy);
|
| + HBasicBlock* CreateBasicBlock(HEnvironment* env);
|
| HBasicBlock* CreateLoopHeaderBlock();
|
|
|
| + HValue* BuildCheckNonSmi(HValue* object);
|
| + HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
|
| +
|
| // Building common constructs
|
| HInstruction* BuildExternalArrayElementAccess(
|
| HValue* external_elements,
|
| @@ -952,7 +1015,7 @@ class HGraphBuilder {
|
|
|
| class CheckBuilder {
|
| public:
|
| - explicit CheckBuilder(HGraphBuilder* builder, BailoutId id);
|
| + explicit CheckBuilder(HGraphBuilder* builder);
|
| ~CheckBuilder() {
|
| if (!finished_) End();
|
| }
|
| @@ -969,37 +1032,127 @@ class HGraphBuilder {
|
| bool finished_;
|
| HBasicBlock* failure_block_;
|
| HBasicBlock* merge_block_;
|
| - BailoutId id_;
|
| };
|
|
|
| class IfBuilder {
|
| public:
|
| - explicit IfBuilder(HGraphBuilder* builder, BailoutId id);
|
| + explicit IfBuilder(HGraphBuilder* builder,
|
| + int position = RelocInfo::kNoPosition);
|
| + IfBuilder(HGraphBuilder* builder,
|
| + HIfContinuation* continuation);
|
| +
|
| ~IfBuilder() {
|
| if (!finished_) End();
|
| }
|
|
|
| - HInstruction* BeginIf(
|
| + HInstruction* IfCompare(
|
| HValue* left,
|
| HValue* right,
|
| Token::Value token,
|
| Representation input_representation = Representation::Integer32());
|
| - HInstruction* BeginIfObjectsEqual(HValue* left, HValue* right);
|
| - HInstruction* BeginIfMapEquals(HValue* value, Handle<Map> map);
|
| - void BeginElse();
|
| +
|
| + HInstruction* IfCompareMap(HValue* left, Handle<Map> map);
|
| +
|
| + template<class Condition>
|
| + HInstruction* If(HValue *p) {
|
| + HControlInstruction* compare = new(zone()) Condition(p);
|
| + AddCompare(compare);
|
| + return compare;
|
| + }
|
| +
|
| + template<class Condition, class P2>
|
| + HInstruction* If(HValue* p1, P2 p2) {
|
| + HControlInstruction* compare = new(zone()) Condition(p1, p2);
|
| + AddCompare(compare);
|
| + return compare;
|
| + }
|
| +
|
| + template<class Condition>
|
| + HInstruction* OrIfCompare(
|
| + HValue* p1,
|
| + HValue* p2,
|
| + Token::Value token,
|
| + Representation input_representation = Representation::Integer32()) {
|
| + Or();
|
| + return IfCompare(p1, p2, token, input_representation);
|
| + }
|
| +
|
| + HInstruction* OrIfCompareMap(HValue* left, Handle<Map> map) {
|
| + Or();
|
| + return IfCompareMap(left, map);
|
| + }
|
| +
|
| + template<class Condition>
|
| + HInstruction* OrIf(HValue *p) {
|
| + Or();
|
| + return If<Condition>(p);
|
| + }
|
| +
|
| + template<class Condition, class P2>
|
| + HInstruction* OrIf(HValue* p1, P2 p2) {
|
| + Or();
|
| + return If<Condition>(p1, p2);
|
| + }
|
| +
|
| + template<class Condition>
|
| + HInstruction* AndIfCompare(
|
| + HValue* p1,
|
| + HValue* p2,
|
| + Token::Value token,
|
| + Representation input_representation = Representation::Integer32()) {
|
| + And();
|
| + return IfCompare(p1, p2, token, input_representation);
|
| + }
|
| +
|
| + HInstruction* AndIfCompareMap(HValue* left, Handle<Map> map) {
|
| + And();
|
| + return IfCompareMap(left, map);
|
| + }
|
| +
|
| + template<class Condition>
|
| + HInstruction* AndIf(HValue *p) {
|
| + And();
|
| + return If<Condition>(p);
|
| + }
|
| +
|
| + template<class Condition, class P2>
|
| + HInstruction* AndIf(HValue* p1, P2 p2) {
|
| + And();
|
| + return If<Condition>(p1, p2);
|
| + }
|
| +
|
| + void Or();
|
| + void And();
|
| +
|
| + void CaptureContinuation(HIfContinuation* continuation);
|
| +
|
| + void Then();
|
| + void Else();
|
| void End();
|
|
|
| + void Deopt();
|
| +
|
| private:
|
| + void AddCompare(HControlInstruction* compare);
|
| +
|
| Zone* zone() { return builder_->zone(); }
|
|
|
| HGraphBuilder* builder_;
|
| - bool finished_;
|
| - bool did_else_;
|
| + int position_;
|
| + bool finished_ : 1;
|
| + bool did_then_ : 1;
|
| + bool did_else_ : 1;
|
| + bool deopt_then_ : 1;
|
| + bool deopt_else_ : 1;
|
| + bool did_and_ : 1;
|
| + bool did_or_ : 1;
|
| + bool captured_ : 1;
|
| + bool needs_compare_ : 1;
|
| HBasicBlock* first_true_block_;
|
| HBasicBlock* last_true_block_;
|
| HBasicBlock* first_false_block_;
|
| + HBasicBlock* split_edge_merge_block_;
|
| HBasicBlock* merge_block_;
|
| - BailoutId id_;
|
| };
|
|
|
| class LoopBuilder {
|
| @@ -1013,8 +1166,7 @@ class HGraphBuilder {
|
|
|
| LoopBuilder(HGraphBuilder* builder,
|
| HValue* context,
|
| - Direction direction,
|
| - BailoutId id);
|
| + Direction direction);
|
| ~LoopBuilder() {
|
| ASSERT(finished_);
|
| }
|
| @@ -1037,7 +1189,6 @@ class HGraphBuilder {
|
| HBasicBlock* body_block_;
|
| HBasicBlock* exit_block_;
|
| Direction direction_;
|
| - BailoutId id_;
|
| bool finished_;
|
| };
|
|
|
| @@ -1063,8 +1214,7 @@ class HGraphBuilder {
|
|
|
| HValue* BuildAllocateElements(HValue* context,
|
| ElementsKind kind,
|
| - HValue* capacity,
|
| - BailoutId ast_id);
|
| + HValue* capacity);
|
|
|
| void BuildInitializeElements(HValue* elements,
|
| ElementsKind kind,
|
| @@ -1078,15 +1228,13 @@ class HGraphBuilder {
|
| HValue* elements,
|
| ElementsKind kind,
|
| HValue* length,
|
| - HValue* new_capacity,
|
| - BailoutId ast_id);
|
| + HValue* new_capacity);
|
|
|
| void BuildFillElementsWithHole(HValue* context,
|
| HValue* elements,
|
| ElementsKind elements_kind,
|
| HValue* from,
|
| - HValue* to,
|
| - BailoutId ast_id);
|
| + HValue* to);
|
|
|
| void BuildCopyElements(HValue* context,
|
| HValue* from_elements,
|
| @@ -1094,8 +1242,7 @@ class HGraphBuilder {
|
| HValue* to_elements,
|
| ElementsKind to_elements_kind,
|
| HValue* length,
|
| - HValue* capacity,
|
| - BailoutId ast_id);
|
| + HValue* capacity);
|
|
|
| HValue* BuildCloneShallowArray(HContext* context,
|
| HValue* boilerplate,
|
|
|