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:
parent
99d541a486
commit
b17713e405
12
src/ast.h
12
src/ast.h
@ -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_;
|
||||
|
@ -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);
|
||||
|
34
src/types.h
34
src/types.h
@ -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_
|
||||
|
117
src/typing.cc
117
src/typing.cc
@ -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_));
|
||||
}
|
||||
|
||||
|
||||
|
15
src/typing.h
15
src/typing.h
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user