Commit b17713e4 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Introduce type Bounds record

Refactoring in anticipation of handling variable bounds.

R=jkummerow@chromium.org
BUG=

Review URL: https://codereview.chromium.org/18415005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15625 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 99d541a4
...@@ -357,10 +357,8 @@ class Expression: public AstNode { ...@@ -357,10 +357,8 @@ class Expression: public AstNode {
bool IsUndefinedLiteral(); bool IsUndefinedLiteral();
// Expression type bounds // Expression type bounds
Handle<Type> upper_type() { return upper_type_; } Bounds bounds() { return bounds_; }
Handle<Type> lower_type() { return lower_type_; } void set_bounds(Bounds bounds) { bounds_ = bounds; }
void set_upper_type(Handle<Type> type) { upper_type_ = type; }
void set_lower_type(Handle<Type> type) { lower_type_ = type; }
// Type feedback information for assignments and properties. // Type feedback information for assignments and properties.
virtual bool IsMonomorphic() { virtual bool IsMonomorphic() {
...@@ -391,15 +389,13 @@ class Expression: public AstNode { ...@@ -391,15 +389,13 @@ class Expression: public AstNode {
protected: protected:
explicit Expression(Isolate* isolate) explicit Expression(Isolate* isolate)
: upper_type_(Type::Any(), isolate), : bounds_(Type::None(), Type::Any(), isolate),
lower_type_(Type::None(), isolate),
id_(GetNextId(isolate)), id_(GetNextId(isolate)),
test_id_(GetNextId(isolate)) {} test_id_(GetNextId(isolate)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; } void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
private: private:
Handle<Type> upper_type_; Bounds bounds_;
Handle<Type> lower_type_;
byte to_boolean_types_; byte to_boolean_types_;
const BailoutId id_; const BailoutId id_;
......
...@@ -7280,12 +7280,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { ...@@ -7280,12 +7280,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else { } else {
VariableProxy* proxy = expr->expression()->AsVariableProxy(); VariableProxy* proxy = expr->expression()->AsVariableProxy();
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
return Bailout("possible direct call to eval"); return Bailout("possible direct call to eval");
} }
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (global_call) { if (global_call) {
Variable* var = proxy->var(); Variable* var = proxy->var();
bool known_global_function = false; bool known_global_function = false;
...@@ -7609,7 +7608,7 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { ...@@ -7609,7 +7608,7 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression())); CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop(); HValue* value = Pop();
Handle<Type> operand_type = expr->expression()->lower_type(); Handle<Type> operand_type = expr->expression()->bounds().lower;
HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
return ast_context()->ReturnInstruction(instr, expr->id()); return ast_context()->ReturnInstruction(instr, expr->id());
} }
...@@ -7618,7 +7617,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { ...@@ -7618,7 +7617,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression())); CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop(); HValue* value = Pop();
Handle<Type> operand_type = expr->expression()->lower_type(); Handle<Type> operand_type = expr->expression()->bounds().lower;
HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
return ast_context()->ReturnInstruction(instr, expr->id()); return ast_context()->ReturnInstruction(instr, expr->id());
} }
...@@ -7954,9 +7953,9 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( ...@@ -7954,9 +7953,9 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
HValue* left, HValue* left,
HValue* right) { HValue* right) {
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
Handle<Type> left_type = expr->left()->lower_type(); Handle<Type> left_type = expr->left()->bounds().lower;
Handle<Type> right_type = expr->right()->lower_type(); Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> result_type = expr->lower_type(); Handle<Type> result_type = expr->bounds().lower;
Maybe<int> fixed_right_arg = expr->fixed_right_arg(); Maybe<int> fixed_right_arg = expr->fixed_right_arg();
Representation left_rep = Representation::FromType(left_type); Representation left_rep = Representation::FromType(left_type);
Representation right_rep = Representation::FromType(right_type); Representation right_rep = Representation::FromType(right_type);
...@@ -8278,8 +8277,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { ...@@ -8278,8 +8277,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return ast_context()->ReturnControl(instr, expr->id()); return ast_context()->ReturnControl(instr, expr->id());
} }
Handle<Type> left_type = expr->left()->lower_type(); Handle<Type> left_type = expr->left()->bounds().lower;
Handle<Type> right_type = expr->right()->lower_type(); Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> combined_type = expr->combined_type(); Handle<Type> combined_type = expr->combined_type();
Representation combined_rep = Representation::FromType(combined_type); Representation combined_rep = Representation::FromType(combined_type);
Representation left_rep = Representation::FromType(left_type); Representation left_rep = Representation::FromType(left_type);
......
...@@ -291,6 +291,40 @@ class Type : public Object { ...@@ -291,6 +291,40 @@ class Type : public Object {
} }
}; };
// A simple struct to represent a pair of lower/upper type bounds.
struct Bounds {
Handle<Type> lower;
Handle<Type> upper;
Bounds() {}
Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) {}
Bounds(Type* l, Type* u, Isolate* isl) : lower(l, isl), upper(u, isl) {}
explicit Bounds(Handle<Type> t) : lower(t), upper(t) {}
Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {}
// Meet: both b1 and b2 are known to hold.
static Bounds Both(Bounds b1, Bounds b2, Isolate* isl) {
return Bounds(
handle(Type::Union(b1.lower, b2.lower), isl),
handle(Type::Intersect(b1.upper, b2.upper), isl));
}
// Join: either b1 or b2 is known to hold.
static Bounds Either(Bounds b1, Bounds b2, Isolate* isl) {
return Bounds(
handle(Type::Intersect(b1.lower, b2.lower), isl),
handle(Type::Union(b1.upper, b2.upper), isl));
}
static Bounds NarrowLower(Bounds b, Handle<Type> t, Isolate* isl) {
return Bounds(handle(Type::Union(b.lower, t), isl), b.upper);
}
static Bounds NarrowUpper(Bounds b, Handle<Type> t, Isolate* isl) {
return Bounds(b.lower, handle(Type::Intersect(b.upper, t), isl));
}
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_TYPES_H_ #endif // V8_TYPES_H_
...@@ -248,12 +248,9 @@ void AstTyper::VisitConditional(Conditional* expr) { ...@@ -248,12 +248,9 @@ void AstTyper::VisitConditional(Conditional* expr) {
expr->condition()->RecordToBooleanTypeFeedback(oracle()); expr->condition()->RecordToBooleanTypeFeedback(oracle());
MergeLowerType(expr, Type::Intersect( NarrowType(expr, Bounds::Either(
expr->then_expression()->lower_type(), expr->then_expression()->bounds(),
expr->else_expression()->lower_type())); expr->else_expression()->bounds(), isolate_));
MergeUpperType(expr, Type::Union(
expr->then_expression()->upper_type(),
expr->else_expression()->upper_type()));
} }
...@@ -264,14 +261,12 @@ void AstTyper::VisitVariableProxy(VariableProxy* expr) { ...@@ -264,14 +261,12 @@ void AstTyper::VisitVariableProxy(VariableProxy* expr) {
void AstTyper::VisitLiteral(Literal* expr) { void AstTyper::VisitLiteral(Literal* expr) {
Type* type = Type::Constant(expr->value(), isolate_); Type* type = Type::Constant(expr->value(), isolate_);
MergeLowerType(expr, type); NarrowType(expr, Bounds(type, isolate_));
MergeUpperType(expr, type);
} }
void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
MergeLowerType(expr, Type::RegExp()); NarrowType(expr, Bounds(Type::RegExp(), isolate_));
MergeUpperType(expr, Type::RegExp());
} }
...@@ -290,8 +285,7 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -290,8 +285,7 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
} }
} }
MergeLowerType(expr, Type::Object()); NarrowType(expr, Bounds(Type::Object(), isolate_));
MergeUpperType(expr, Type::Object());
} }
...@@ -302,8 +296,7 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -302,8 +296,7 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
RECURSE(Visit(value)); RECURSE(Visit(value));
} }
MergeLowerType(expr, Type::Array()); NarrowType(expr, Bounds(Type::Array(), isolate_));
MergeUpperType(expr, Type::Array());
} }
...@@ -320,6 +313,8 @@ void AstTyper::VisitAssignment(Assignment* expr) { ...@@ -320,6 +313,8 @@ void AstTyper::VisitAssignment(Assignment* expr) {
expr->RecordTypeFeedback(oracle(), zone()); expr->RecordTypeFeedback(oracle(), zone());
} }
} }
NarrowType(expr, expr->binary_operation()->bounds());
} else { } else {
RECURSE(Visit(expr->target())); RECURSE(Visit(expr->target()));
RECURSE(Visit(expr->value())); RECURSE(Visit(expr->value()));
...@@ -328,8 +323,7 @@ void AstTyper::VisitAssignment(Assignment* expr) { ...@@ -328,8 +323,7 @@ void AstTyper::VisitAssignment(Assignment* expr) {
expr->RecordTypeFeedback(oracle(), zone()); expr->RecordTypeFeedback(oracle(), zone());
} }
MergeLowerType(expr, expr->value()->lower_type()); NarrowType(expr, expr->value()->bounds());
MergeUpperType(expr, expr->value()->upper_type());
} }
// TODO(rossberg): handle target variables // TODO(rossberg): handle target variables
} }
...@@ -346,8 +340,7 @@ void AstTyper::VisitYield(Yield* expr) { ...@@ -346,8 +340,7 @@ void AstTyper::VisitYield(Yield* expr) {
void AstTyper::VisitThrow(Throw* expr) { void AstTyper::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception())); RECURSE(Visit(expr->exception()));
// Lower type is None already. NarrowType(expr, Bounds(Type::None(), isolate_));
MergeUpperType(expr, Type::None());
} }
...@@ -412,7 +405,7 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -412,7 +405,7 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
// Collect type feedback. // Collect type feedback.
Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId()); Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId());
MergeLowerType(expr->expression(), op_type); NarrowLowerType(expr->expression(), op_type);
if (expr->op() == Token::NOT) { if (expr->op() == Token::NOT) {
// TODO(rossberg): only do in test or value context. // TODO(rossberg): only do in test or value context.
expr->expression()->RecordToBooleanTypeFeedback(oracle()); expr->expression()->RecordToBooleanTypeFeedback(oracle());
...@@ -421,27 +414,23 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -421,27 +414,23 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) { switch (expr->op()) {
case Token::NOT: case Token::NOT:
case Token::DELETE: case Token::DELETE:
MergeLowerType(expr, Type::Boolean()); NarrowType(expr, Bounds(Type::Boolean(), isolate_));
MergeUpperType(expr, Type::Boolean());
break; break;
case Token::VOID: case Token::VOID:
MergeLowerType(expr, Type::Undefined()); NarrowType(expr, Bounds(Type::Undefined(), isolate_));
MergeUpperType(expr, Type::Undefined());
break; break;
case Token::ADD: case Token::ADD:
case Token::SUB: { case Token::SUB: {
MergeLowerType(expr, Type::Smi()); Type* upper = *expr->expression()->bounds().upper;
Type* upper = *expr->expression()->upper_type(); if (!upper->Is(Type::Number())) upper = Type::Number();
MergeUpperType(expr, upper->Is(Type::Number()) ? upper : Type::Number()); NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
break; break;
} }
case Token::BIT_NOT: case Token::BIT_NOT:
MergeLowerType(expr, Type::Smi()); NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
MergeUpperType(expr, Type::Signed32());
break; break;
case Token::TYPEOF: case Token::TYPEOF:
MergeLowerType(expr, Type::InternalizedString()); NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
MergeUpperType(expr, Type::InternalizedString());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -458,8 +447,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) { ...@@ -458,8 +447,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
prop->RecordTypeFeedback(oracle(), zone()); prop->RecordTypeFeedback(oracle(), zone());
} }
MergeLowerType(expr, Type::Smi()); NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
MergeUpperType(expr, Type::Number());
} }
...@@ -472,9 +460,9 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -472,9 +460,9 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
Maybe<int> fixed_right_arg; Maybe<int> fixed_right_arg;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(), oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
&left_type, &right_type, &type, &fixed_right_arg); &left_type, &right_type, &type, &fixed_right_arg);
MergeLowerType(expr, type); NarrowLowerType(expr, type);
MergeLowerType(expr->left(), left_type); NarrowLowerType(expr->left(), left_type);
MergeLowerType(expr->right(), right_type); NarrowLowerType(expr->right(), right_type);
expr->set_fixed_right_arg(fixed_right_arg); expr->set_fixed_right_arg(fixed_right_arg);
if (expr->op() == Token::OR || expr->op() == Token::AND) { if (expr->op() == Token::OR || expr->op() == Token::AND) {
expr->left()->RecordToBooleanTypeFeedback(oracle()); expr->left()->RecordToBooleanTypeFeedback(oracle());
...@@ -482,56 +470,50 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -482,56 +470,50 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) { switch (expr->op()) {
case Token::COMMA: case Token::COMMA:
MergeLowerType(expr, expr->right()->lower_type()); NarrowType(expr, expr->right()->bounds());
MergeUpperType(expr, expr->right()->upper_type());
break; break;
case Token::OR: case Token::OR:
case Token::AND: case Token::AND:
MergeLowerType(expr, Type::Intersect( NarrowType(expr, Bounds::Either(
expr->left()->lower_type(), expr->right()->lower_type())); expr->left()->bounds(), expr->right()->bounds(), isolate_));
MergeUpperType(expr, Type::Union(
expr->left()->upper_type(), expr->right()->upper_type()));
break; break;
case Token::BIT_OR: case Token::BIT_OR:
case Token::BIT_AND: { case Token::BIT_AND: {
MergeLowerType(expr, Type::Smi()); Type* upper = Type::Union(
Type* upper = expr->left()->bounds().upper, expr->right()->bounds().upper);
Type::Union(expr->left()->upper_type(), expr->right()->upper_type()); if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
MergeUpperType(expr, NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
upper->Is(Type::Signed32()) ? upper : Type::Signed32());
break; break;
} }
case Token::BIT_XOR: case Token::BIT_XOR:
case Token::SHL: case Token::SHL:
case Token::SAR: case Token::SAR:
MergeLowerType(expr, Type::Smi()); NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
MergeUpperType(expr, Type::Signed32());
break; break;
case Token::SHR: case Token::SHR:
MergeLowerType(expr, Type::Smi()); NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_));
MergeUpperType(expr, Type::Unsigned32());
break; break;
case Token::ADD: { case Token::ADD: {
Handle<Type> l = expr->left()->lower_type(); Bounds l = expr->left()->bounds();
Handle<Type> r = expr->right()->lower_type(); Bounds r = expr->right()->bounds();
MergeLowerType(expr, Type* lower =
l->Is(Type::Number()) && r->Is(Type::Number()) ? Type::Smi() : l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
l->Is(Type::String()) || r->Is(Type::String()) ? Type::String() : Type::Smi() :
Type::None()); l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
l = expr->left()->upper_type(); Type::String() : Type::None();
r = expr->right()->upper_type(); Type* upper =
MergeUpperType(expr, l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
l->Is(Type::Number()) && r->Is(Type::Number()) ? Type::Number() : Type::Number() :
l->Is(Type::String()) || r->Is(Type::String()) ? Type::String() : l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
Type::NumberOrString()); Type::String() : Type::NumberOrString();
NarrowType(expr, Bounds(lower, upper, isolate_));
break; break;
} }
case Token::SUB: case Token::SUB:
case Token::MUL: case Token::MUL:
case Token::DIV: case Token::DIV:
case Token::MOD: case Token::MOD:
MergeLowerType(expr, Type::Smi()); NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
MergeUpperType(expr, Type::Number());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -547,12 +529,11 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) { ...@@ -547,12 +529,11 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
Handle<Type> left_type, right_type, combined_type; Handle<Type> left_type, right_type, combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(), oracle()->CompareType(expr->CompareOperationFeedbackId(),
&left_type, &right_type, &combined_type); &left_type, &right_type, &combined_type);
MergeLowerType(expr->left(), left_type); NarrowLowerType(expr->left(), left_type);
MergeLowerType(expr->right(), right_type); NarrowLowerType(expr->right(), right_type);
expr->set_combined_type(combined_type); expr->set_combined_type(combined_type);
MergeLowerType(expr, Type::Boolean()); NarrowType(expr, Bounds(Type::Boolean(), isolate_));
MergeUpperType(expr, Type::Boolean());
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "ast.h" #include "ast.h"
#include "compiler.h" #include "compiler.h"
#include "type-info.h" #include "type-info.h"
#include "types.h"
#include "zone.h" #include "zone.h"
#include "scopes.h" #include "scopes.h"
...@@ -62,17 +63,11 @@ class AstTyper: public AstVisitor { ...@@ -62,17 +63,11 @@ class AstTyper: public AstVisitor {
TypeFeedbackOracle* oracle() { return &oracle_; } TypeFeedbackOracle* oracle() { return &oracle_; }
Zone* zone() const { return info_->zone(); } Zone* zone() const { return info_->zone(); }
void MergeLowerType(Expression* e, Handle<Type> t) { void NarrowType(Expression* e, Bounds b) {
e->set_lower_type(handle(Type::Union(e->lower_type(), t), isolate_)); e->set_bounds(Bounds::Both(e->bounds(), b, isolate_));
} }
void MergeUpperType(Expression* e, Handle<Type> t) { void NarrowLowerType(Expression* e, Handle<Type> t) {
e->set_upper_type(handle(Type::Intersect(e->upper_type(), t), isolate_)); e->set_bounds(Bounds::NarrowLower(e->bounds(), t, isolate_));
}
void MergeLowerType(Expression* e, Type* t) {
MergeLowerType(e, handle(t, isolate_));
}
void MergeUpperType(Expression* e, Type* t) {
MergeUpperType(e, handle(t, isolate_));
} }
void VisitDeclarations(ZoneList<Declaration*>* declarations); void VisitDeclarations(ZoneList<Declaration*>* declarations);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment