Commit bb04e124 authored by vogelheim's avatar vogelheim Committed by Commit bot

Remove Expression::bounds_, in order to conserve memory during parsing.

Expression::bounds_ is used only by a subset of compile passes, but the
data structure occupies space for every Expression node ever parsed. This
unneccessarily increases memory consumption. Particularly, peak memory
consumption during startup, which may cause out-of-memory errors.

This CL
- removes Expression::bounds_;
- introduces an AstTypeBounds container, which mappes Expression* to Bounds;
- modifies the code that actually requires bounds information, namely
  Crankshaft compile and AsmWasmBuilder, to instantiate such an AstTypeBounds
  container before typing and to pass it to the code that consumes this
  information; and
- modifies all accesses to Expression::bounds_ to instead access the bounds
  via the container instead.

Additionally, this rewrites test-ast-expression-visitor. The reason is that
this code attempted to test AstExpressionVisitor but did so exclusively
through its subclass ExpressionTypeCollector, meaning that the test dealt
almost exclusively with type bounds despite the class-under-test having
no knowledge or functionality related to it. Worse, the test was written
in a way to assume that type bounds were available outside & after
compilation, which is something this change changes.

BUG=v8:4947

Review-Url: https://codereview.chromium.org/1968383002
Cr-Commit-Position: refs/heads/master@{#36222}
parent d0b6686c
......@@ -774,6 +774,7 @@ v8_source_set("v8_base") {
"src/ast/ast-literal-reindexer.h",
"src/ast/ast-numbering.cc",
"src/ast/ast-numbering.h",
"src/ast/ast-type-bounds.h",
"src/ast/ast-value-factory.cc",
"src/ast/ast-value-factory.h",
"src/ast/ast.cc",
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A container to associate type bounds with AST Expression nodes.
#ifndef V8_AST_AST_TYPE_BOUNDS_H_
#define V8_AST_AST_TYPE_BOUNDS_H_
#include "src/types.h"
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
class Expression;
class AstTypeBounds {
public:
explicit AstTypeBounds(Zone* zone) : bounds_map_(zone) {}
~AstTypeBounds() {}
Bounds get(Expression* expression) const {
ZoneMap<Expression*, Bounds>::const_iterator i =
bounds_map_.find(expression);
return (i != bounds_map_.end()) ? i->second : Bounds::Unbounded();
}
void set(Expression* expression, Bounds bounds) {
bounds_map_[expression] = bounds;
}
private:
ZoneMap<Expression*, Bounds> bounds_map_;
};
} // namespace internal
} // namespace v8
#endif // V8_AST_AST_TYPE_BOUNDS_H_
......@@ -337,10 +337,6 @@ class Expression : public AstNode {
// True iff the expression is a valid target for an assignment.
bool IsValidReferenceExpressionOrThis() const;
// Expression type bounds
Bounds bounds() const { return bounds_; }
void set_bounds(Bounds bounds) { bounds_ = bounds; }
// Type feedback information for assignments and properties.
virtual bool IsMonomorphic() {
UNREACHABLE();
......@@ -374,7 +370,6 @@ class Expression : public AstNode {
Expression(Zone* zone, int pos)
: AstNode(pos),
base_id_(BailoutId::None().ToInt()),
bounds_(Bounds::Unbounded()),
bit_field_(0) {}
static int parent_num_ids() { return 0; }
void set_to_boolean_types(uint16_t types) {
......@@ -390,7 +385,6 @@ class Expression : public AstNode {
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int base_id_;
Bounds bounds_;
class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
uint16_t bit_field_;
// Ends with 16-bit field; deriving classes in turn begin with
......
......@@ -167,11 +167,6 @@ HCompilationJob::Status HCompilationJob::CreateGraphImpl() {
isolate()->GetHTracer()->TraceCompilation(info());
}
// Type-check the function.
AstTyper(info()->isolate(), info()->zone(), info()->closure(),
info()->scope(), info()->osr_ast_id(), info()->literal())
.Run();
// Optimization could have been disabled by the parser. Note that this check
// is only needed because the Hydrogen graph builder is missing some bailouts.
if (info()->shared_info()->optimization_disabled()) {
......@@ -184,6 +179,12 @@ HCompilationJob::Status HCompilationJob::CreateGraphImpl() {
? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
: new (info()->zone()) HOptimizedGraphBuilder(info());
// Type-check the function.
AstTyper(info()->isolate(), info()->zone(), info()->closure(),
info()->scope(), info()->osr_ast_id(), info()->literal(),
graph_builder->bounds())
.Run();
graph_ = graph_builder->CreateGraph();
if (isolate()->has_pending_exception()) {
......@@ -3683,7 +3684,8 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
break_scope_(NULL),
inlined_count_(0),
globals_(10, info->zone()),
osr_(new (info->zone()) HOsrBuilder(this)) {
osr_(new (info->zone()) HOsrBuilder(this)),
bounds_(info->zone()) {
// This is not initialized in the initializer list because the
// constructor for the initial state relies on function_state_ == NULL
// to know it's the initial state.
......@@ -5172,7 +5174,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
CHECK_ALIVE(VisitForValue(stmt->tag()));
Add<HSimulate>(stmt->EntryId());
HValue* tag_value = Top();
Type* tag_type = stmt->tag()->bounds().lower;
Type* tag_type = bounds_.get(stmt->tag()).lower;
// 1. Build all the tests, with dangling true branches
BailoutId default_id = BailoutId::None();
......@@ -5189,7 +5191,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
HValue* label_value = Pop();
Type* label_type = clause->label()->bounds().lower;
Type* label_type = bounds_.get(clause->label()).lower;
Type* combined_type = clause->compare_type();
HControlInstruction* compare = BuildCompareInstruction(
Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
......@@ -8653,7 +8655,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
// Type-check the inlined function.
DCHECK(target_shared->has_deoptimization_support());
AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
target_info.scope(), target_info.osr_ast_id(), target_info.literal())
target_info.scope(), target_info.osr_ast_id(), target_info.literal(),
&bounds_)
.Run();
int inlining_id = 0;
......@@ -11127,9 +11130,9 @@ HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
HValue* left,
HValue* right,
PushBeforeSimulateBehavior push_sim_result) {
Type* left_type = expr->left()->bounds().lower;
Type* right_type = expr->right()->bounds().lower;
Type* result_type = expr->bounds().lower;
Type* left_type = bounds_.get(expr->left()).lower;
Type* right_type = bounds_.get(expr->right()).lower;
Type* result_type = bounds_.get(expr).lower;
Maybe<int> fixed_right_arg = expr->fixed_right_arg();
Handle<AllocationSite> allocation_site = expr->allocation_site();
......@@ -11664,8 +11667,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return ast_context()->ReturnControl(instr, expr->id());
}
Type* left_type = expr->left()->bounds().lower;
Type* right_type = expr->right()->bounds().lower;
Type* left_type = bounds_.get(expr->left()).lower;
Type* right_type = bounds_.get(expr->right()).lower;
Type* combined_type = expr->combined_type();
CHECK_ALIVE(VisitForValue(expr->left()));
......
......@@ -7,6 +7,7 @@
#include "src/accessors.h"
#include "src/allocation.h"
#include "src/ast/ast-type-bounds.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/bailout-reason.h"
......@@ -2183,6 +2184,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
AstTypeBounds* bounds() { return &bounds_; }
void* operator new(size_t size, Zone* zone) { return zone->New(size); }
void operator delete(void* pointer, Zone* zone) { }
void operator delete(void* pointer) { }
......@@ -2916,6 +2919,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
HOsrBuilder* osr_;
AstTypeBounds bounds_;
friend class FunctionState; // Pushes and pops the state stack.
friend class AstContext; // Pushes and pops the AST context stack.
friend class KeyedLoadFastElementStub;
......
......@@ -14,9 +14,9 @@
namespace v8 {
namespace internal {
AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root)
Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root,
AstTypeBounds* bounds)
: isolate_(isolate),
zone_(zone),
closure_(closure),
......@@ -26,7 +26,8 @@ AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
oracle_(isolate, zone, handle(closure->shared()->code()),
handle(closure->shared()->feedback_vector()),
handle(closure->context()->native_context())),
store_(zone) {
store_(zone),
bounds_(bounds) {
InitializeAstVisitor(isolate);
}
......@@ -346,7 +347,7 @@ void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
void AstTyper::VisitDoExpression(DoExpression* expr) {
RECURSE(VisitBlock(expr->block()));
RECURSE(VisitVariableProxy(expr->result()));
NarrowType(expr, expr->result()->bounds());
NarrowType(expr, bounds_->get(expr->result()));
}
......@@ -364,9 +365,9 @@ void AstTyper::VisitConditional(Conditional* expr) {
then_effects.Alt(else_effects);
store_.Seq(then_effects);
NarrowType(expr, Bounds::Either(
expr->then_expression()->bounds(),
expr->else_expression()->bounds(), zone()));
NarrowType(expr,
Bounds::Either(bounds_->get(expr->then_expression()),
bounds_->get(expr->else_expression()), zone()));
}
......@@ -457,11 +458,11 @@ void AstTyper::VisitAssignment(Assignment* expr) {
expr->is_compound() ? expr->binary_operation() : expr->value();
RECURSE(Visit(expr->target()));
RECURSE(Visit(rhs));
NarrowType(expr, rhs->bounds());
NarrowType(expr, bounds_->get(rhs));
VariableProxy* proxy = expr->target()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
}
}
......@@ -621,7 +622,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
}
}
......@@ -649,7 +650,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::COMMA:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
NarrowType(expr, expr->right()->bounds());
NarrowType(expr, bounds_->get(expr->right()));
break;
case Token::OR:
case Token::AND: {
......@@ -662,16 +663,16 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
left_effects.Alt(right_effects);
store_.Seq(left_effects);
NarrowType(expr, Bounds::Either(
expr->left()->bounds(), expr->right()->bounds(), zone()));
NarrowType(expr, Bounds::Either(bounds_->get(expr->left()),
bounds_->get(expr->right()), zone()));
break;
}
case Token::BIT_OR:
case Token::BIT_AND: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
Type* upper = Type::Union(
expr->left()->bounds().upper, expr->right()->bounds().upper, zone());
Type* upper = Type::Union(bounds_->get(expr->left()).upper,
bounds_->get(expr->right()).upper, zone());
if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone());
NarrowType(expr, Bounds(lower, upper));
......@@ -695,8 +696,8 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::ADD: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
Bounds l = expr->left()->bounds();
Bounds r = expr->right()->bounds();
Bounds l = bounds_->get(expr->left());
Bounds r = bounds_->get(expr->right());
Type* lower =
!l.lower->IsInhabited() || !r.lower->IsInhabited()
? Type::None()
......
......@@ -6,6 +6,7 @@
#define V8_CRANKSHAFT_TYPING_H_
#include "src/allocation.h"
#include "src/ast/ast-type-bounds.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/effects.h"
......@@ -16,11 +17,11 @@
namespace v8 {
namespace internal {
class AstTyper: public AstVisitor {
public:
AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root);
Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root,
AstTypeBounds* bounds);
void Run();
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
......@@ -41,15 +42,16 @@ class AstTyper: public AstVisitor {
FunctionLiteral* root_;
TypeFeedbackOracle oracle_;
Store store_;
AstTypeBounds* bounds_;
Zone* zone() const { return zone_; }
TypeFeedbackOracle* oracle() { return &oracle_; }
void NarrowType(Expression* e, Bounds b) {
e->set_bounds(Bounds::Both(e->bounds(), b, zone()));
bounds_->set(e, Bounds::Both(bounds_->get(e), b, zone()));
}
void NarrowLowerType(Expression* e, Type* t) {
e->set_bounds(Bounds::NarrowLower(e->bounds(), t, zone()));
bounds_->set(e, Bounds::NarrowLower(bounds_->get(e), t, zone()));
}
Effects EnterEffects() {
......
......@@ -62,7 +62,8 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
in_function_(false),
building_function_tables_(false),
visiting_exports_(false),
cache_(TypeCache::Get()) {
cache_(TypeCache::Get()),
bounds_(zone) {
InitializeAstVisitor(isolate);
InitializeStdlib();
}
......@@ -494,11 +495,11 @@ void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
Scope* scope = expr->scope();
DCHECK(scope->is_function_scope());
if (!expr->bounds().upper->IsFunction()) {
if (!bounds_.get(expr).upper->IsFunction()) {
FAIL(expr, "invalid function literal");
}
Type* type = expr->bounds().upper;
Type* type = bounds_.get(expr).upper;
Type* save_return_type = return_type_;
return_type_ = type->AsFunction()->Result();
in_function_ = true;
......@@ -803,7 +804,7 @@ void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
FAIL(right, "heap access shift must match element size");
}
}
expr->key()->set_bounds(Bounds(cache_.kAsmSigned));
bounds_.set(expr->key(), Bounds(cache_.kAsmSigned));
}
Type* result_type;
if (type->Is(cache_.kAsmIntArrayElement)) {
......@@ -954,7 +955,7 @@ void AsmTyper::CheckPolymorphicStdlibArguments(
}
// Handle polymorphic stdlib functions specially.
Expression* arg0 = args->at(0);
Type* arg0_type = arg0->bounds().upper;
Type* arg0_type = bounds_.get(arg0).upper;
switch (standard_member) {
case kMathFround: {
if (!arg0_type->Is(cache_.kAsmFloat) &&
......@@ -983,8 +984,8 @@ void AsmTyper::CheckPolymorphicStdlibArguments(
FAIL(arg0, "illegal function argument type");
}
if (args->length() > 1) {
Type* other = Type::Intersect(args->at(0)->bounds().upper,
args->at(1)->bounds().upper, zone());
Type* other = Type::Intersect(bounds_.get(args->at(0)).upper,
bounds_.get(args->at(1)).upper, zone());
if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
!other->Is(cache_.kAsmSigned)) {
FAIL(arg0, "function arguments types don't match");
......@@ -1031,8 +1032,8 @@ void AsmTyper::VisitCall(Call* expr) {
}
}
intish_ = 0;
expr->expression()->set_bounds(
Bounds(Type::Function(Type::Any(), zone())));
bounds_.set(expr->expression(),
Bounds(Type::Function(Type::Any(), zone())));
IntersectResult(expr, expected_type);
} else {
if (fun_type->Arity() != args->length()) {
......@@ -1198,11 +1199,12 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
cache_.kAsmSigned, true));
if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
Type::Number()->Is(expr->left()->bounds().upper)) {
Type::Number()->Is(bounds_.get(expr->left()).upper)) {
// Force the return types of foreign functions.
expr->left()->set_bounds(Bounds(cache_.kAsmSigned));
bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
}
if (in_function_ && !expr->left()->bounds().upper->Is(cache_.kAsmIntQ)) {
if (in_function_ &&
!bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
FAIL(expr->left(), "intish required");
}
return;
......@@ -1212,7 +1214,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
Literal* left = expr->left()->AsLiteral();
if (left && left->value()->IsBoolean()) {
if (left->ToBooleanIsTrue()) {
left->set_bounds(Bounds(cache_.kSingletonOne));
bounds_.set(left, Bounds(cache_.kSingletonOne));
RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
"not operator expects an integer"));
IntersectResult(expr, cache_.kAsmSigned);
......@@ -1299,13 +1301,13 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
// For unary +, expressed as x * 1.0
if (expr->left()->IsCall() &&
Type::Number()->Is(expr->left()->bounds().upper)) {
Type::Number()->Is(bounds_.get(expr->left()).upper)) {
// Force the return types of foreign functions.
expr->left()->set_bounds(Bounds(cache_.kAsmDouble));
left_type = expr->left()->bounds().upper;
bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
left_type = bounds_.get(expr->left()).upper;
}
if (!(expr->left()->IsProperty() &&
Type::Number()->Is(expr->left()->bounds().upper))) {
Type::Number()->Is(bounds_.get(expr->left()).upper))) {
if (!left_type->Is(cache_.kAsmSigned) &&
!left_type->Is(cache_.kAsmUnsigned) &&
!left_type->Is(cache_.kAsmFixnum) &&
......@@ -1323,7 +1325,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
!expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
// For unary -, expressed as x * -1
expr->right()->set_bounds(Bounds(cache_.kAsmDouble));
bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
IntersectResult(expr, cache_.kAsmDouble);
return;
} else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
......@@ -1589,14 +1591,14 @@ AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
void AsmTyper::SetResult(Expression* expr, Type* type) {
computed_type_ = type;
expr->set_bounds(Bounds(computed_type_));
bounds_.set(expr, Bounds(computed_type_));
}
void AsmTyper::IntersectResult(Expression* expr, Type* type) {
computed_type_ = type;
Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
expr->set_bounds(Bounds(bounded_type));
bounds_.set(expr, Bounds(bounded_type));
}
......
......@@ -6,6 +6,7 @@
#define V8_TYPING_ASM_H_
#include "src/allocation.h"
#include "src/ast/ast-type-bounds.h"
#include "src/ast/ast.h"
#include "src/effects.h"
#include "src/type-info.h"
......@@ -24,6 +25,7 @@ class AsmTyper : public AstVisitor {
bool Validate();
void set_allow_simd(bool simd) { allow_simd_ = simd; }
const char* error_message() { return error_message_; }
const AstTypeBounds* bounds() { return &bounds_; }
enum StandardMember {
kNone = 0,
......@@ -117,6 +119,8 @@ class AsmTyper : public AstVisitor {
TypeCache const& cache_;
AstTypeBounds bounds_;
static const int kErrorMessageLimit = 100;
char error_message_[kErrorMessageLimit];
......
......@@ -430,6 +430,7 @@
'ast/ast-literal-reindexer.h',
'ast/ast-numbering.cc',
'ast/ast-numbering.h',
'ast/ast-type-bounds.h',
'ast/ast-value-factory.cc',
'ast/ast-value-factory.h',
'ast/ast.cc',
......
......@@ -60,7 +60,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
function_tables_(HashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
imported_function_table_(this) {
imported_function_table_(this),
bounds_(typer->bounds()) {
InitializeAstVisitor(isolate);
}
......@@ -320,7 +321,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
Literal* label = clause->label()->AsLiteral();
Handle<Object> value = label->value();
DCHECK(value->IsNumber() &&
label->bounds().upper->Is(cache_.kAsmSigned));
bounds_->get(label).upper->Is(cache_.kAsmSigned));
int32_t label_value;
if (!value->ToInt32(&label_value)) {
UNREACHABLE();
......@@ -414,8 +415,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
void VisitFunctionLiteral(FunctionLiteral* expr) {
Scope* scope = expr->scope();
if (scope_ == kFuncScope) {
if (expr->bounds().lower->IsFunction()) {
FunctionType* func_type = expr->bounds().lower->AsFunction();
if (bounds_->get(expr).lower->IsFunction()) {
FunctionType* func_type = bounds_->get(expr).lower->AsFunction();
LocalType return_type = TypeFrom(func_type->Result());
current_function_builder_->ReturnType(return_type);
for (int i = 0; i < expr->parameter_count(); i++) {
......@@ -523,7 +524,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) {
return;
}
Type* type = expr->bounds().upper;
Type* type = bounds_->get(expr).upper;
if (type->Is(cache_.kAsmSigned)) {
int32_t i = 0;
if (!value->ToInt32(&i)) {
......@@ -585,7 +586,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) {
FunctionType* func_type =
funcs->bounds().lower->AsArray()->Element()->AsFunction();
bounds_->get(funcs).lower->AsArray()->Element()->AsFunction();
LocalType return_type = TypeFrom(func_type->Result());
FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
func_type->Arity());
......@@ -758,8 +759,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
if (target_prop != nullptr) {
// Left hand side is a property access, i.e. the asm.js heap.
if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
expr->target()->AsProperty()->obj()->bounds().lower->Is(
cache_.kFloat32Array)) {
bounds_->get(expr->target()->AsProperty()->obj())
.lower->Is(cache_.kFloat32Array)) {
current_function_builder_->Emit(kExprF32ConvertF64);
}
WasmOpcode opcode;
......@@ -799,7 +800,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
if (vp != nullptr && vp->var()->IsParameter() &&
vp->var()->index() == 1) {
VariableProxy* target = expr->target()->AsVariableProxy();
if (target->bounds().lower->Is(Type::Function())) {
if (bounds_->get(target).lower->Is(Type::Function())) {
const AstRawString* name =
prop->key()->AsLiteral()->AsRawPropertyName();
imported_function_table_.AddImport(target->var(), name->raw_data(),
......@@ -811,7 +812,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
if (funcs != nullptr &&
funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
bounds_->get(funcs).lower->AsArray()->Element()->IsFunction()) {
VariableProxy* target = expr->target()->AsVariableProxy();
DCHECK_NOT_NULL(target);
AddFunctionTable(target, funcs);
......@@ -890,8 +891,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) {
Expression* obj = expr->obj();
DCHECK_EQ(obj->bounds().lower, obj->bounds().upper);
Type* type = obj->bounds().lower;
DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper);
Type* type = bounds_->get(obj).lower;
int size;
if (type->Is(cache_.kUint8Array)) {
*mtype = MachineType::Uint8();
......@@ -1261,7 +1262,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
uint16_t index;
VariableProxy* vp = expr->expression()->AsVariableProxy();
if (vp != nullptr &&
Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) {
Type::Any()->Is(bounds_->get(vp).lower->AsFunction()->Result())) {
LocalType return_type = TypeOf(expr);
ZoneList<Expression*>* args = expr->arguments();
FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
......@@ -1582,8 +1583,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
TypeIndex TypeIndexOf(Expression* expr) {
DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
Type* type = expr->bounds().lower;
DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper);
Type* type = bounds_->get(expr).lower;
if (type->Is(cache_.kAsmFixnum)) {
return kFixnum;
} else if (type->Is(cache_.kAsmSigned)) {
......@@ -1688,8 +1689,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
LocalType TypeOf(Expression* expr) {
DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
return TypeFrom(expr->bounds().lower);
DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper);
return TypeFrom(bounds_->get(expr).lower);
}
LocalType TypeFrom(Type* type) {
......@@ -1723,6 +1724,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
uint32_t next_table_index_;
ZoneHashMap function_tables_;
ImportedFunctionTable imported_function_table_;
const AstTypeBounds* bounds_;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
......
......@@ -6,6 +6,7 @@
#include "test/cctest/expression-type-collector.h"
#include "src/ast/ast-type-bounds.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/codegen.h"
......@@ -27,12 +28,10 @@ struct {
} // namespace
ExpressionTypeCollector::ExpressionTypeCollector(
Isolate* isolate, FunctionLiteral* root,
Isolate* isolate, FunctionLiteral* root, const AstTypeBounds* bounds,
ZoneVector<ExpressionTypeEntry>* dst)
: AstExpressionVisitor(isolate, root), result_(dst) {}
: AstExpressionVisitor(isolate, root), bounds_(bounds), result_(dst) {}
void ExpressionTypeCollector::Run() {
result_->clear();
......@@ -47,7 +46,7 @@ void ExpressionTypeCollector::VisitExpression(Expression* expression) {
if (proxy) {
e.name = proxy->raw_name();
}
e.bounds = expression->bounds();
e.bounds = bounds_->get(expression);
AstNode::NodeType type = expression->node_type();
e.kind = "unknown";
for (size_t i = 0; i < arraysize(NodeTypeNameList); ++i) {
......
......@@ -10,6 +10,8 @@
namespace v8 {
namespace internal {
class AstTypeBounds;
// A Visitor over an AST that collects a human readable string summarizing
// structure and types. Used for testing of the typing information attached
// to the expression nodes of an AST.
......@@ -24,6 +26,7 @@ struct ExpressionTypeEntry {
class ExpressionTypeCollector : public AstExpressionVisitor {
public:
ExpressionTypeCollector(Isolate* isolate, FunctionLiteral* root,
const AstTypeBounds* bounds,
ZoneVector<ExpressionTypeEntry>* dst);
void Run();
......@@ -31,6 +34,7 @@ class ExpressionTypeCollector : public AstExpressionVisitor {
void VisitExpression(Expression* expression);
private:
const AstTypeBounds* bounds_;
ZoneVector<ExpressionTypeEntry>* result_;
};
} // namespace internal
......
......@@ -72,7 +72,7 @@ std::string Validate(Zone* zone, const char* source,
info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
AsmTyper typer(isolate, zone, *script, root);
if (typer.Validate()) {
ExpressionTypeCollector(isolate, root, types).Run();
ExpressionTypeCollector(isolate, root, typer.bounds(), types).Run();
return "";
} else {
return typer.error_message();
......
This diff is collapsed.
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