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
This commit is contained in:
rossberg@chromium.org 2013-07-11 11:47:05 +00:00
parent 99d541a486
commit b17713e405
5 changed files with 100 additions and 95 deletions

View File

@ -357,10 +357,8 @@ class Expression: public AstNode {
bool IsUndefinedLiteral();
// Expression type bounds
Handle<Type> upper_type() { return upper_type_; }
Handle<Type> lower_type() { return lower_type_; }
void set_upper_type(Handle<Type> type) { upper_type_ = type; }
void set_lower_type(Handle<Type> type) { lower_type_ = type; }
Bounds bounds() { return bounds_; }
void set_bounds(Bounds bounds) { bounds_ = bounds; }
// Type feedback information for assignments and properties.
virtual bool IsMonomorphic() {
@ -391,15 +389,13 @@ class Expression: public AstNode {
protected:
explicit Expression(Isolate* isolate)
: upper_type_(Type::Any(), isolate),
lower_type_(Type::None(), isolate),
: bounds_(Type::None(), Type::Any(), isolate),
id_(GetNextId(isolate)),
test_id_(GetNextId(isolate)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
private:
Handle<Type> upper_type_;
Handle<Type> lower_type_;
Bounds bounds_;
byte to_boolean_types_;
const BailoutId id_;

View File

@ -7280,12 +7280,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
return Bailout("possible direct call to eval");
}
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (global_call) {
Variable* var = proxy->var();
bool known_global_function = false;
@ -7609,7 +7608,7 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
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);
return ast_context()->ReturnInstruction(instr, expr->id());
}
@ -7618,7 +7617,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
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);
return ast_context()->ReturnInstruction(instr, expr->id());
}
@ -7954,9 +7953,9 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
HValue* left,
HValue* right) {
HValue* context = environment()->LookupContext();
Handle<Type> left_type = expr->left()->lower_type();
Handle<Type> right_type = expr->right()->lower_type();
Handle<Type> result_type = expr->lower_type();
Handle<Type> left_type = expr->left()->bounds().lower;
Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> result_type = expr->bounds().lower;
Maybe<int> fixed_right_arg = expr->fixed_right_arg();
Representation left_rep = Representation::FromType(left_type);
Representation right_rep = Representation::FromType(right_type);
@ -8278,8 +8277,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return ast_context()->ReturnControl(instr, expr->id());
}
Handle<Type> left_type = expr->left()->lower_type();
Handle<Type> right_type = expr->right()->lower_type();
Handle<Type> left_type = expr->left()->bounds().lower;
Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> combined_type = expr->combined_type();
Representation combined_rep = Representation::FromType(combined_type);
Representation left_rep = Representation::FromType(left_type);

View File

@ -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
#endif // V8_TYPES_H_

View File

@ -248,12 +248,9 @@ void AstTyper::VisitConditional(Conditional* expr) {
expr->condition()->RecordToBooleanTypeFeedback(oracle());
MergeLowerType(expr, Type::Intersect(
expr->then_expression()->lower_type(),
expr->else_expression()->lower_type()));
MergeUpperType(expr, Type::Union(
expr->then_expression()->upper_type(),
expr->else_expression()->upper_type()));
NarrowType(expr, Bounds::Either(
expr->then_expression()->bounds(),
expr->else_expression()->bounds(), isolate_));
}
@ -264,14 +261,12 @@ void AstTyper::VisitVariableProxy(VariableProxy* expr) {
void AstTyper::VisitLiteral(Literal* expr) {
Type* type = Type::Constant(expr->value(), isolate_);
MergeLowerType(expr, type);
MergeUpperType(expr, type);
NarrowType(expr, Bounds(type, isolate_));
}
void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
MergeLowerType(expr, Type::RegExp());
MergeUpperType(expr, Type::RegExp());
NarrowType(expr, Bounds(Type::RegExp(), isolate_));
}
@ -290,8 +285,7 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
MergeLowerType(expr, Type::Object());
MergeUpperType(expr, Type::Object());
NarrowType(expr, Bounds(Type::Object(), isolate_));
}
@ -302,8 +296,7 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
RECURSE(Visit(value));
}
MergeLowerType(expr, Type::Array());
MergeUpperType(expr, Type::Array());
NarrowType(expr, Bounds(Type::Array(), isolate_));
}
@ -320,6 +313,8 @@ void AstTyper::VisitAssignment(Assignment* expr) {
expr->RecordTypeFeedback(oracle(), zone());
}
}
NarrowType(expr, expr->binary_operation()->bounds());
} else {
RECURSE(Visit(expr->target()));
RECURSE(Visit(expr->value()));
@ -328,8 +323,7 @@ void AstTyper::VisitAssignment(Assignment* expr) {
expr->RecordTypeFeedback(oracle(), zone());
}
MergeLowerType(expr, expr->value()->lower_type());
MergeUpperType(expr, expr->value()->upper_type());
NarrowType(expr, expr->value()->bounds());
}
// TODO(rossberg): handle target variables
}
@ -346,8 +340,7 @@ void AstTyper::VisitYield(Yield* expr) {
void AstTyper::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception()));
// Lower type is None already.
MergeUpperType(expr, Type::None());
NarrowType(expr, Bounds(Type::None(), isolate_));
}
@ -412,7 +405,7 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
// Collect type feedback.
Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId());
MergeLowerType(expr->expression(), op_type);
NarrowLowerType(expr->expression(), op_type);
if (expr->op() == Token::NOT) {
// TODO(rossberg): only do in test or value context.
expr->expression()->RecordToBooleanTypeFeedback(oracle());
@ -421,27 +414,23 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::NOT:
case Token::DELETE:
MergeLowerType(expr, Type::Boolean());
MergeUpperType(expr, Type::Boolean());
NarrowType(expr, Bounds(Type::Boolean(), isolate_));
break;
case Token::VOID:
MergeLowerType(expr, Type::Undefined());
MergeUpperType(expr, Type::Undefined());
NarrowType(expr, Bounds(Type::Undefined(), isolate_));
break;
case Token::ADD:
case Token::SUB: {
MergeLowerType(expr, Type::Smi());
Type* upper = *expr->expression()->upper_type();
MergeUpperType(expr, upper->Is(Type::Number()) ? upper : Type::Number());
Type* upper = *expr->expression()->bounds().upper;
if (!upper->Is(Type::Number())) upper = Type::Number();
NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
break;
}
case Token::BIT_NOT:
MergeLowerType(expr, Type::Smi());
MergeUpperType(expr, Type::Signed32());
NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
break;
case Token::TYPEOF:
MergeLowerType(expr, Type::InternalizedString());
MergeUpperType(expr, Type::InternalizedString());
NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
break;
default:
UNREACHABLE();
@ -458,8 +447,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
prop->RecordTypeFeedback(oracle(), zone());
}
MergeLowerType(expr, Type::Smi());
MergeUpperType(expr, Type::Number());
NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
}
@ -472,9 +460,9 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
Maybe<int> fixed_right_arg;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
&left_type, &right_type, &type, &fixed_right_arg);
MergeLowerType(expr, type);
MergeLowerType(expr->left(), left_type);
MergeLowerType(expr->right(), right_type);
NarrowLowerType(expr, type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
expr->set_fixed_right_arg(fixed_right_arg);
if (expr->op() == Token::OR || expr->op() == Token::AND) {
expr->left()->RecordToBooleanTypeFeedback(oracle());
@ -482,56 +470,50 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
MergeLowerType(expr, expr->right()->lower_type());
MergeUpperType(expr, expr->right()->upper_type());
NarrowType(expr, expr->right()->bounds());
break;
case Token::OR:
case Token::AND:
MergeLowerType(expr, Type::Intersect(
expr->left()->lower_type(), expr->right()->lower_type()));
MergeUpperType(expr, Type::Union(
expr->left()->upper_type(), expr->right()->upper_type()));
NarrowType(expr, Bounds::Either(
expr->left()->bounds(), expr->right()->bounds(), isolate_));
break;
case Token::BIT_OR:
case Token::BIT_AND: {
MergeLowerType(expr, Type::Smi());
Type* upper =
Type::Union(expr->left()->upper_type(), expr->right()->upper_type());
MergeUpperType(expr,
upper->Is(Type::Signed32()) ? upper : Type::Signed32());
Type* upper = Type::Union(
expr->left()->bounds().upper, expr->right()->bounds().upper);
if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
break;
}
case Token::BIT_XOR:
case Token::SHL:
case Token::SAR:
MergeLowerType(expr, Type::Smi());
MergeUpperType(expr, Type::Signed32());
NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
break;
case Token::SHR:
MergeLowerType(expr, Type::Smi());
MergeUpperType(expr, Type::Unsigned32());
NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_));
break;
case Token::ADD: {
Handle<Type> l = expr->left()->lower_type();
Handle<Type> r = expr->right()->lower_type();
MergeLowerType(expr,
l->Is(Type::Number()) && r->Is(Type::Number()) ? Type::Smi() :
l->Is(Type::String()) || r->Is(Type::String()) ? Type::String() :
Type::None());
l = expr->left()->upper_type();
r = expr->right()->upper_type();
MergeUpperType(expr,
l->Is(Type::Number()) && r->Is(Type::Number()) ? Type::Number() :
l->Is(Type::String()) || r->Is(Type::String()) ? Type::String() :
Type::NumberOrString());
Bounds l = expr->left()->bounds();
Bounds r = expr->right()->bounds();
Type* lower =
l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
Type::Smi() :
l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
Type::String() : Type::None();
Type* upper =
l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
Type::Number() :
l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
Type::String() : Type::NumberOrString();
NarrowType(expr, Bounds(lower, upper, isolate_));
break;
}
case Token::SUB:
case Token::MUL:
case Token::DIV:
case Token::MOD:
MergeLowerType(expr, Type::Smi());
MergeUpperType(expr, Type::Number());
NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
break;
default:
UNREACHABLE();
@ -547,12 +529,11 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
Handle<Type> left_type, right_type, combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(),
&left_type, &right_type, &combined_type);
MergeLowerType(expr->left(), left_type);
MergeLowerType(expr->right(), right_type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
expr->set_combined_type(combined_type);
MergeLowerType(expr, Type::Boolean());
MergeUpperType(expr, Type::Boolean());
NarrowType(expr, Bounds(Type::Boolean(), isolate_));
}

View File

@ -34,6 +34,7 @@
#include "ast.h"
#include "compiler.h"
#include "type-info.h"
#include "types.h"
#include "zone.h"
#include "scopes.h"
@ -62,17 +63,11 @@ class AstTyper: public AstVisitor {
TypeFeedbackOracle* oracle() { return &oracle_; }
Zone* zone() const { return info_->zone(); }
void MergeLowerType(Expression* e, Handle<Type> t) {
e->set_lower_type(handle(Type::Union(e->lower_type(), t), isolate_));
void NarrowType(Expression* e, Bounds b) {
e->set_bounds(Bounds::Both(e->bounds(), b, isolate_));
}
void MergeUpperType(Expression* e, Handle<Type> t) {
e->set_upper_type(handle(Type::Intersect(e->upper_type(), 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 NarrowLowerType(Expression* e, Handle<Type> t) {
e->set_bounds(Bounds::NarrowLower(e->bounds(), t, isolate_));
}
void VisitDeclarations(ZoneList<Declaration*>* declarations);