From 7657955f3f8a488fc0879a5b3ea60e413a174de4 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Tue, 2 Mar 2010 14:00:59 +0000 Subject: [PATCH] Add syntax checker for side-effect-free expressions to AstOptimizer in rewriter.cc. Add bit fields for syntax checker results to Expression in ast.h. Review URL: http://codereview.chromium.org/660372 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3998 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ast.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/rewriter.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/ast.h b/src/ast.h index 927a9f5..ba8b980 100644 --- a/src/ast.h +++ b/src/ast.h @@ -183,7 +183,11 @@ class Expression: public AstNode { static const int kNoLabel = -1; - Expression() : num_(kNoLabel), def_(NULL), defined_vars_(NULL) {} + Expression() + : bitfields_(0), + num_(kNoLabel), + def_(NULL), + defined_vars_(NULL) {} virtual Expression* AsExpression() { return this; } @@ -225,11 +229,66 @@ class Expression: public AstNode { defined_vars_ = defined_vars; } + // AST analysis results + + // True if the expression rooted at this node can be compiled by the + // side-effect free compiler. + bool side_effect_free() { return SideEffectFreeField::decode(bitfields_); } + void set_side_effect_free(bool is_side_effect_free) { + bitfields_ = (bitfields_ & ~SideEffectFreeField::mask()) | + SideEffectFreeField::encode(is_side_effect_free); + } + + // The number of unary and binary operations contained in the expression + // rooted at this node. Valid only if side_effect_free() is true. + int expression_size() { return ExpressionSizeField::decode(bitfields_); } + void set_expression_size(int expression_size) { + bitfields_ = (bitfields_ & ~ExpressionSizeField::mask()) | + ExpressionSizeField::encode(Min(expression_size, ExpressionSizeMax)); + } + + // The number of expression stack slots needed to compute the expression + // rooted at this node. Does not count the slot needed by the value + // computed by this expression. Valid only if side_effect_free() is true. + int stack_height() { return StackHeightField::decode(bitfields_); } + void set_stack_height(int stack_height) { + bitfields_ &= ~StackHeightField::mask(); + bitfields_ |= + StackHeightField::encode(Min(stack_height, StackHeightMax)); + } + private: + uint32_t bitfields_; StaticType type_; + int num_; DefinitionInfo* def_; ZoneList* defined_vars_; + + static const int SideEffectFreeFieldStart = 0; + static const int SideEffectFreeFieldLength = 1; + class SideEffectFreeField: public BitField { + }; + + static const int ExpressionSizeFieldStart = + SideEffectFreeFieldStart + SideEffectFreeFieldLength; + static const int ExpressionSizeFieldLength = 5; + static const int ExpressionSizeMax = (1 << ExpressionSizeFieldLength) - 1; + class ExpressionSizeField: public BitField { + }; + + static const int StackHeightFieldStart = + ExpressionSizeFieldStart + ExpressionSizeFieldLength; + static const int StackHeightFieldLength = 5; + static const int StackHeightMax = (1 << StackHeightFieldLength) - 1; + class StackHeightField: public BitField { + }; }; diff --git a/src/rewriter.cc b/src/rewriter.cc index b05cfae..db84243 100644 --- a/src/rewriter.cc +++ b/src/rewriter.cc @@ -244,6 +244,14 @@ void AstOptimizer::VisitVariableProxy(VariableProxy* node) { !Heap::result_symbol()->Equals(*var->name())) { func_name_inferrer_.PushName(var->name()); } + + if (var->slot() != NULL) { + Slot* slot = var->slot(); + node->set_side_effect_free( + (slot->type() == Slot::LOCAL && !slot->is_arguments()) || + slot->type() == Slot::PARAMETER)); + // stack_height and expression_size remain 0. + } } } @@ -252,11 +260,16 @@ void AstOptimizer::VisitLiteral(Literal* node) { Handle literal = node->handle(); if (literal->IsSmi()) { node->type()->SetAsLikelySmi(); + node->set_side_effect_free(true); + // stack_height and expression_size remain 0. } else if (literal->IsString()) { Handle lit_str(Handle::cast(literal)); if (!Heap::prototype_symbol()->Equals(*lit_str)) { func_name_inferrer_.PushName(lit_str); } + } else if (literal->IsHeapNumber()) { + node->set_side_effect_free(true); + // stack_height and expression_size remain 0. } } @@ -414,6 +427,23 @@ void AstOptimizer::VisitCallRuntime(CallRuntime* node) { void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { Visit(node->expression()); + switch (node->op()) { + case Token::ADD: + case Token::SUB: + node->set_side_effect_free(node->expression()->side_effect_free()); + node->set_expression_size(node->expression()->expression_size() + 1); + node->set_stack_height(node->expression()->stack_height()); + break; + case Token::DELETE: + case Token::TYPEOF: + case Token::VOID: + case Token::BIT_NOT: + case Token::NOT: + break; + default: + UNREACHABLE(); + break; + } } @@ -483,6 +513,33 @@ void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) { } } } + switch (node->op()) { + case Token::COMMA: + case Token::OR: + case Token::AND: + case Token::BIT_OR: + case Token::BIT_XOR: + case Token::BIT_AND: + case Token::SHL: + case Token::SAR: + case Token::SHR: + case Token::MOD: + break; + case Token::ADD: + case Token::SUB: + case Token::MUL: + case Token::DIV: + node->set_side_effect_free(node->left()->side_effect_free() && + node->right()->side_effect_free()); + node->set_expression_size(node->left()->expression_size() + + node->right()->expression_size() + 1); + node->set_stack_height(Max(node->left()->stack_height(), + node->right()->stack_height() + 1)); + break; + default: + UNREACHABLE(); + break; + } } -- 2.7.4