Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc
index 30f8464..ee5427b 100644
--- a/src/wasm/asm-wasm-builder.cc
+++ b/src/wasm/asm-wasm-builder.cc
@@ -27,7 +27,8 @@
class AsmWasmBuilderImpl : public AstVisitor {
public:
- AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal)
+ AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
+ Handle<Object> foreign)
: local_variables_(HashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
@@ -44,17 +45,23 @@
literal_(literal),
isolate_(isolate),
zone_(zone),
+ foreign_(foreign),
cache_(TypeCache::Get()),
breakable_blocks_(zone),
block_size_(0),
- init_function_index(0) {
+ init_function_index_(0),
+ next_table_index_(0),
+ function_tables_(HashMap::PointersMatch,
+ ZoneHashMap::kDefaultHashMapCapacity,
+ ZoneAllocationPolicy(zone)),
+ imported_function_table_(this) {
InitializeAstVisitor(isolate);
}
void InitializeInitFunction() {
unsigned char init[] = "__init__";
- init_function_index = builder_->AddFunction();
- current_function_builder_ = builder_->FunctionAt(init_function_index);
+ init_function_index_ = builder_->AddFunction();
+ current_function_builder_ = builder_->FunctionAt(init_function_index_);
current_function_builder_->SetName(init, 8);
current_function_builder_->ReturnType(kAstStmt);
current_function_builder_->Exported(1);
@@ -70,7 +77,7 @@
void VisitFunctionDeclaration(FunctionDeclaration* decl) {
DCHECK(!in_function_);
- DCHECK(current_function_builder_ == nullptr);
+ DCHECK_NULL(current_function_builder_);
uint16_t index = LookupOrInsertFunction(decl->proxy()->var());
current_function_builder_ = builder_->FunctionAt(index);
in_function_ = true;
@@ -103,11 +110,15 @@
}
}
}
- DCHECK(in_function_);
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
- static_cast<byte>(stmt->statements()->length()));
- RECURSE(VisitStatements(stmt->statements()));
- DCHECK(block_size_ >= 0);
+ if (in_function_) {
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock,
+ false,
+ static_cast<byte>(stmt->statements()->length()));
+ RECURSE(VisitStatements(stmt->statements()));
+ DCHECK(block_size_ >= 0);
+ } else {
+ RECURSE(VisitStatements(stmt->statements()));
+ }
}
class BlockVisitor {
@@ -162,7 +173,7 @@
void VisitContinueStatement(ContinueStatement* stmt) {
DCHECK(in_function_);
- DCHECK(stmt->target() != NULL);
+ DCHECK_NOT_NULL(stmt->target());
int i = static_cast<int>(breakable_blocks_.size()) - 1;
int block_distance = 0;
for (; i >= 0; i--) {
@@ -183,7 +194,7 @@
void VisitBreakStatement(BreakStatement* stmt) {
DCHECK(in_function_);
- DCHECK(stmt->target() != NULL);
+ DCHECK_NOT_NULL(stmt->target());
int i = static_cast<int>(breakable_blocks_.size()) - 1;
int block_distance = 0;
for (; i >= 0; i--) {
@@ -229,7 +240,7 @@
void CompileCase(CaseClause* clause, uint16_t fall_through,
VariableProxy* tag) {
Literal* label = clause->label()->AsLiteral();
- DCHECK(label != nullptr);
+ DCHECK_NOT_NULL(label);
block_size_++;
current_function_builder_->Emit(kExprIf);
current_function_builder_->Emit(kExprI32Ior);
@@ -247,7 +258,7 @@
void VisitSwitchStatement(SwitchStatement* stmt) {
VariableProxy* tag = stmt->tag()->AsVariableProxy();
- DCHECK(tag != NULL);
+ DCHECK_NOT_NULL(tag);
BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
0);
uint16_t fall_through = current_function_builder_->AddLocal(kAstI32);
@@ -332,20 +343,20 @@
Scope* scope = expr->scope();
if (in_function_) {
if (expr->bounds().lower->IsFunction()) {
- Type::FunctionType* func_type = expr->bounds().lower->AsFunction();
+ FunctionType* func_type = expr->bounds().lower->AsFunction();
LocalType return_type = TypeFrom(func_type->Result());
current_function_builder_->ReturnType(return_type);
for (int i = 0; i < expr->parameter_count(); i++) {
LocalType type = TypeFrom(func_type->Parameter(i));
- DCHECK(type != kAstStmt);
+ DCHECK_NE(kAstStmt, type);
LookupOrInsertLocal(scope->parameter(i), type);
}
} else {
UNREACHABLE();
}
}
- RECURSE(VisitDeclarations(scope->declarations()));
RECURSE(VisitStatements(expr->body()));
+ RECURSE(VisitDeclarations(scope->declarations()));
}
void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
@@ -363,34 +374,26 @@
void VisitVariableProxy(VariableProxy* expr) {
if (in_function_) {
Variable* var = expr->var();
- if (var->is_function()) {
- DCHECK(!is_set_op_);
- std::vector<uint8_t> index =
- UnsignedLEB128From(LookupOrInsertFunction(var));
- current_function_builder_->EmitCode(
- &index[0], static_cast<uint32_t>(index.size()));
- } else {
- if (is_set_op_) {
- if (var->IsContextSlot()) {
- current_function_builder_->Emit(kExprStoreGlobal);
- } else {
- current_function_builder_->Emit(kExprSetLocal);
- }
- is_set_op_ = false;
- } else {
- if (var->IsContextSlot()) {
- current_function_builder_->Emit(kExprLoadGlobal);
- } else {
- current_function_builder_->Emit(kExprGetLocal);
- }
- }
- LocalType var_type = TypeOf(expr);
- DCHECK(var_type != kAstStmt);
+ if (is_set_op_) {
if (var->IsContextSlot()) {
- AddLeb128(LookupOrInsertGlobal(var, var_type), false);
+ current_function_builder_->Emit(kExprStoreGlobal);
} else {
- AddLeb128(LookupOrInsertLocal(var, var_type), true);
+ current_function_builder_->Emit(kExprSetLocal);
}
+ is_set_op_ = false;
+ } else {
+ if (var->IsContextSlot()) {
+ current_function_builder_->Emit(kExprLoadGlobal);
+ } else {
+ current_function_builder_->Emit(kExprGetLocal);
+ }
+ }
+ LocalType var_type = TypeOf(expr);
+ DCHECK_NE(kAstStmt, var_type);
+ if (var->IsContextSlot()) {
+ AddLeb128(LookupOrInsertGlobal(var, var_type), false);
+ } else {
+ AddLeb128(LookupOrInsertLocal(var, var_type), true);
}
}
}
@@ -433,10 +436,10 @@
ObjectLiteralProperty* prop = props->at(i);
DCHECK(marking_exported);
VariableProxy* expr = prop->value()->AsVariableProxy();
- DCHECK(expr != nullptr);
+ DCHECK_NOT_NULL(expr);
Variable* var = expr->var();
Literal* name = prop->key()->AsLiteral();
- DCHECK(name != nullptr);
+ DCHECK_NOT_NULL(name);
DCHECK(name->IsPropertyName());
const AstRawString* raw_name = name->AsRawPropertyName();
if (var->is_function()) {
@@ -451,7 +454,7 @@
void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); }
void LoadInitFunction() {
- current_function_builder_ = builder_->FunctionAt(init_function_index);
+ current_function_builder_ = builder_->FunctionAt(init_function_index_);
in_function_ = true;
}
@@ -460,11 +463,155 @@
current_function_builder_ = nullptr;
}
+ void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) {
+ FunctionType* func_type =
+ funcs->bounds().lower->AsArray()->Element()->AsFunction();
+ LocalType return_type = TypeFrom(func_type->Result());
+ FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
+ func_type->Arity());
+ if (return_type != kAstStmt) {
+ sig.AddReturn(static_cast<LocalType>(return_type));
+ }
+ for (int i = 0; i < func_type->Arity(); i++) {
+ sig.AddParam(TypeFrom(func_type->Parameter(i)));
+ }
+ uint16_t signature_index = builder_->AddSignature(sig.Build());
+ InsertFunctionTable(table->var(), next_table_index_, signature_index);
+ next_table_index_ += funcs->values()->length();
+ for (int i = 0; i < funcs->values()->length(); i++) {
+ VariableProxy* func = funcs->values()->at(i)->AsVariableProxy();
+ DCHECK_NOT_NULL(func);
+ builder_->AddIndirectFunction(LookupOrInsertFunction(func->var()));
+ }
+ }
+
+ struct FunctionTableIndices : public ZoneObject {
+ uint32_t start_index;
+ uint16_t signature_index;
+ };
+
+ void InsertFunctionTable(Variable* v, uint32_t start_index,
+ uint16_t signature_index) {
+ FunctionTableIndices* container = new (zone()) FunctionTableIndices();
+ container->start_index = start_index;
+ container->signature_index = signature_index;
+ ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert(
+ v, ComputePointerHash(v), ZoneAllocationPolicy(zone()));
+ entry->value = container;
+ }
+
+ FunctionTableIndices* LookupFunctionTable(Variable* v) {
+ ZoneHashMap::Entry* entry =
+ function_tables_.Lookup(v, ComputePointerHash(v));
+ DCHECK_NOT_NULL(entry);
+ return reinterpret_cast<FunctionTableIndices*>(entry->value);
+ }
+
+ class ImportedFunctionTable {
+ private:
+ class ImportedFunctionIndices : public ZoneObject {
+ public:
+ const unsigned char* name_;
+ int name_length_;
+ WasmModuleBuilder::SignatureMap signature_to_index_;
+
+ ImportedFunctionIndices(const unsigned char* name, int name_length,
+ Zone* zone)
+ : name_(name), name_length_(name_length), signature_to_index_(zone) {}
+ };
+ ZoneHashMap table_;
+ AsmWasmBuilderImpl* builder_;
+
+ public:
+ explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder)
+ : table_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
+ ZoneAllocationPolicy(builder->zone())),
+ builder_(builder) {}
+
+ void AddImport(Variable* v, const unsigned char* name, int name_length) {
+ ImportedFunctionIndices* indices = new (builder_->zone())
+ ImportedFunctionIndices(name, name_length, builder_->zone());
+ ZoneHashMap::Entry* entry = table_.LookupOrInsert(
+ v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone()));
+ entry->value = indices;
+ }
+
+ uint16_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
+ ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v));
+ DCHECK_NOT_NULL(entry);
+ ImportedFunctionIndices* indices =
+ reinterpret_cast<ImportedFunctionIndices*>(entry->value);
+ WasmModuleBuilder::SignatureMap::iterator pos =
+ indices->signature_to_index_.find(sig);
+ if (pos != indices->signature_to_index_.end()) {
+ return pos->second;
+ } else {
+ uint16_t index = builder_->builder_->AddFunction();
+ indices->signature_to_index_[sig] = index;
+ WasmFunctionBuilder* function = builder_->builder_->FunctionAt(index);
+ function->External(1);
+ function->SetName(indices->name_, indices->name_length_);
+ if (sig->return_count() > 0) {
+ function->ReturnType(sig->GetReturn());
+ }
+ for (size_t i = 0; i < sig->parameter_count(); i++) {
+ function->AddParam(sig->GetParam(i));
+ }
+ return index;
+ }
+ }
+ };
+
void VisitAssignment(Assignment* expr) {
bool in_init = false;
if (!in_function_) {
+ BinaryOperation* binop = expr->value()->AsBinaryOperation();
+ if (binop != nullptr) {
+ Property* prop = binop->left()->AsProperty();
+ DCHECK_NOT_NULL(prop);
+ LoadInitFunction();
+ is_set_op_ = true;
+ RECURSE(Visit(expr->target()));
+ DCHECK(!is_set_op_);
+ if (binop->op() == Token::MUL) {
+ DCHECK(binop->right()->IsLiteral());
+ DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
+ DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot());
+ VisitForeignVariable(true, prop);
+ } else if (binop->op() == Token::BIT_OR) {
+ DCHECK(binop->right()->IsLiteral());
+ DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
+ DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot());
+ VisitForeignVariable(false, prop);
+ } else {
+ UNREACHABLE();
+ }
+ UnLoadInitFunction();
+ return;
+ }
// TODO(bradnelson): Get rid of this.
if (TypeOf(expr->value()) == kAstStmt) {
+ Property* prop = expr->value()->AsProperty();
+ if (prop != nullptr) {
+ VariableProxy* vp = prop->obj()->AsVariableProxy();
+ if (vp != nullptr && vp->var()->IsParameter() &&
+ vp->var()->index() == 1) {
+ VariableProxy* target = expr->target()->AsVariableProxy();
+ if (target->bounds().lower->Is(Type::Function())) {
+ const AstRawString* name =
+ prop->key()->AsLiteral()->AsRawPropertyName();
+ imported_function_table_.AddImport(
+ target->var(), name->raw_data(), name->length());
+ }
+ }
+ }
+ ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
+ if (funcs != nullptr &&
+ funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
+ VariableProxy* target = expr->target()->AsVariableProxy();
+ DCHECK_NOT_NULL(target);
+ AddFunctionTable(target, funcs);
+ }
return;
}
in_init = true;
@@ -493,10 +640,59 @@
void VisitThrow(Throw* expr) { UNREACHABLE(); }
+ void VisitForeignVariable(bool is_float, Property* expr) {
+ DCHECK(expr->obj()->AsVariableProxy());
+ DCHECK(VariableLocation::PARAMETER ==
+ expr->obj()->AsVariableProxy()->var()->location());
+ DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index());
+ Literal* key_literal = expr->key()->AsLiteral();
+ DCHECK_NOT_NULL(key_literal);
+ if (!key_literal->value().is_null() && !foreign_.is_null() &&
+ foreign_->IsObject()) {
+ Handle<Name> name =
+ i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
+ MaybeHandle<Object> maybe_value = i::Object::GetProperty(foreign_, name);
+ if (!maybe_value.is_null()) {
+ Handle<Object> value = maybe_value.ToHandleChecked();
+ if (is_float) {
+ MaybeHandle<Object> maybe_nvalue = i::Object::ToNumber(value);
+ if (!maybe_nvalue.is_null()) {
+ Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
+ if (nvalue->IsNumber()) {
+ double val = nvalue->Number();
+ byte code[] = {WASM_F64(val)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ return;
+ }
+ }
+ } else {
+ MaybeHandle<Object> maybe_nvalue =
+ i::Object::ToInt32(isolate_, value);
+ if (!maybe_nvalue.is_null()) {
+ Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
+ if (nvalue->IsNumber()) {
+ int32_t val = static_cast<int32_t>(nvalue->Number());
+ byte code[] = {WASM_I32(val)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (is_float) {
+ byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ } else {
+ byte code[] = {WASM_I32(0)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ }
+ }
+
void VisitProperty(Property* expr) {
Expression* obj = expr->obj();
- DCHECK(obj->bounds().lower == obj->bounds().upper);
- TypeImpl<ZoneTypeConfig>* type = obj->bounds().lower;
+ DCHECK_EQ(obj->bounds().lower, obj->bounds().upper);
+ Type* type = obj->bounds().lower;
MachineType mtype;
int size;
if (type->Is(cache_.kUint8Array)) {
@@ -533,29 +729,38 @@
WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_),
WasmOpcodes::LoadStoreAccessOf(false));
is_set_op_ = false;
- Literal* value = expr->key()->AsLiteral();
- if (value) {
- DCHECK(value->raw_value()->IsNumber());
- DCHECK(kAstI32 == TypeOf(value));
- int val = static_cast<int>(value->raw_value()->AsNumber());
- byte code[] = {WASM_I32(val * size)};
- current_function_builder_->EmitCode(code, sizeof(code));
+ if (size == 1) {
+ // Allow more general expression in byte arrays than the spec
+ // strictly permits.
+ // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in
+ // places that strictly should be HEAP8[HEAP32[..]>>0].
+ RECURSE(Visit(expr->key()));
return;
- }
- BinaryOperation* binop = expr->key()->AsBinaryOperation();
- if (binop) {
- DCHECK(Token::SAR == binop->op());
- DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
- DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
- DCHECK(size ==
- 1 << static_cast<int>(
- binop->right()->AsLiteral()->raw_value()->AsNumber()));
- // Mask bottom bits to match asm.js behavior.
- current_function_builder_->Emit(kExprI32And);
- byte code[] = {WASM_I8(~(size - 1))};
- current_function_builder_->EmitCode(code, sizeof(code));
- RECURSE(Visit(binop->left()));
- return;
+ } else {
+ Literal* value = expr->key()->AsLiteral();
+ if (value) {
+ DCHECK(value->raw_value()->IsNumber());
+ DCHECK_EQ(kAstI32, TypeOf(value));
+ int val = static_cast<int>(value->raw_value()->AsNumber());
+ byte code[] = {WASM_I32(val * size)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ return;
+ }
+ BinaryOperation* binop = expr->key()->AsBinaryOperation();
+ if (binop) {
+ DCHECK_EQ(Token::SAR, binop->op());
+ DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
+ DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
+ DCHECK_EQ(size,
+ 1 << static_cast<int>(
+ binop->right()->AsLiteral()->raw_value()->AsNumber()));
+ // Mask bottom bits to match asm.js behavior.
+ current_function_builder_->Emit(kExprI32And);
+ byte code[] = {WASM_I8(~(size - 1))};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ RECURSE(Visit(binop->left()));
+ return;
+ }
}
UNREACHABLE();
}
@@ -565,18 +770,54 @@
switch (call_type) {
case Call::OTHER_CALL: {
DCHECK(in_function_);
- current_function_builder_->Emit(kExprCallFunction);
- RECURSE(Visit(expr->expression()));
- ZoneList<Expression*>* args = expr->arguments();
- for (int i = 0; i < args->length(); ++i) {
- Expression* arg = args->at(i);
- RECURSE(Visit(arg));
+ uint16_t index;
+ VariableProxy* vp = expr->expression()->AsVariableProxy();
+ if (vp != nullptr &&
+ Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) {
+ LocalType return_type = TypeOf(expr);
+ ZoneList<Expression*>* args = expr->arguments();
+ FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
+ args->length());
+ if (return_type != kAstStmt) {
+ sig.AddReturn(return_type);
+ }
+ for (int i = 0; i < args->length(); i++) {
+ sig.AddParam(TypeOf(args->at(i)));
+ }
+ index =
+ imported_function_table_.GetFunctionIndex(vp->var(), sig.Build());
+ } else {
+ index = LookupOrInsertFunction(vp->var());
}
+ current_function_builder_->Emit(kExprCallFunction);
+ std::vector<uint8_t> index_arr = UnsignedLEB128From(index);
+ current_function_builder_->EmitCode(
+ &index_arr[0], static_cast<uint32_t>(index_arr.size()));
+ break;
+ }
+ case Call::KEYED_PROPERTY_CALL: {
+ DCHECK(in_function_);
+ Property* p = expr->expression()->AsProperty();
+ DCHECK_NOT_NULL(p);
+ VariableProxy* var = p->obj()->AsVariableProxy();
+ DCHECK_NOT_NULL(var);
+ FunctionTableIndices* indices = LookupFunctionTable(var->var());
+ current_function_builder_->EmitWithU8(kExprCallIndirect,
+ indices->signature_index);
+ current_function_builder_->Emit(kExprI32Add);
+ byte code[] = {WASM_I32(indices->start_index)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ RECURSE(Visit(p->key()));
break;
}
default:
UNREACHABLE();
}
+ ZoneList<Expression*>* args = expr->arguments();
+ for (int i = 0; i < args->length(); ++i) {
+ Expression* arg = args->at(i);
+ RECURSE(Visit(arg));
+ }
}
void VisitCallNew(CallNew* expr) { UNREACHABLE(); }
@@ -586,7 +827,7 @@
void VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::NOT: {
- DCHECK(TypeOf(expr->expression()) == kAstI32);
+ DCHECK_EQ(kAstI32, TypeOf(expr->expression()));
current_function_builder_->Emit(kExprBoolNot);
break;
}
@@ -600,7 +841,7 @@
bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op,
int32_t val) {
- DCHECK(expr->right() != nullptr);
+ DCHECK_NOT_NULL(expr->right());
if (expr->op() == op && expr->right()->IsLiteral() &&
TypeOf(expr) == kAstI32) {
Literal* right = expr->right()->AsLiteral();
@@ -614,7 +855,7 @@
bool MatchDoubleBinaryOperation(BinaryOperation* expr, Token::Value op,
double val) {
- DCHECK(expr->right() != nullptr);
+ DCHECK_NOT_NULL(expr->right());
if (expr->op() == op && expr->right()->IsLiteral() &&
TypeOf(expr) == kAstF64) {
Literal* right = expr->right()->AsLiteral();
@@ -629,8 +870,9 @@
enum ConvertOperation { kNone, kAsIs, kToInt, kToDouble };
ConvertOperation MatchOr(BinaryOperation* expr) {
- if (MatchIntBinaryOperation(expr, Token::BIT_OR, 0)) {
- return (TypeOf(expr->left()) == kAstI32) ? kAsIs : kToInt;
+ if (MatchIntBinaryOperation(expr, Token::BIT_OR, 0) &&
+ (TypeOf(expr->left()) == kAstI32)) {
+ return kAsIs;
} else {
return kNone;
}
@@ -647,12 +889,12 @@
ConvertOperation MatchXor(BinaryOperation* expr) {
if (MatchIntBinaryOperation(expr, Token::BIT_XOR, 0xffffffff)) {
- DCHECK(TypeOf(expr->left()) == kAstI32);
- DCHECK(TypeOf(expr->right()) == kAstI32);
+ DCHECK_EQ(kAstI32, TypeOf(expr->left()));
+ DCHECK_EQ(kAstI32, TypeOf(expr->right()));
BinaryOperation* op = expr->left()->AsBinaryOperation();
if (op != nullptr) {
if (MatchIntBinaryOperation(op, Token::BIT_XOR, 0xffffffff)) {
- DCHECK(TypeOf(op->right()) == kAstI32);
+ DCHECK_EQ(kAstI32, TypeOf(op->right()));
if (TypeOf(op->left()) != kAstI32) {
return kToInt;
} else {
@@ -666,7 +908,7 @@
ConvertOperation MatchMul(BinaryOperation* expr) {
if (MatchDoubleBinaryOperation(expr, Token::MUL, 1.0)) {
- DCHECK(TypeOf(expr->right()) == kAstF64);
+ DCHECK_EQ(kAstF64, TypeOf(expr->right()));
if (TypeOf(expr->left()) != kAstF64) {
return kToDouble;
} else {
@@ -768,6 +1010,7 @@
BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true);
BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false);
BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true);
+ BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true);
BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true);
BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true);
BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true);
@@ -786,6 +1029,10 @@
}
break;
}
+ case Token::COMMA: {
+ current_function_builder_->EmitWithU8(kExprBlock, 2);
+ break;
+ }
default:
UNREACHABLE();
}
@@ -879,8 +1126,8 @@
}
TypeIndex TypeIndexOf(Expression* expr) {
- DCHECK(expr->bounds().lower == expr->bounds().upper);
- TypeImpl<ZoneTypeConfig>* type = expr->bounds().lower;
+ DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
+ Type* type = expr->bounds().lower;
if (type->Is(cache_.kAsmFixnum)) {
return kFixnum;
} else if (type->Is(cache_.kAsmSigned)) {
@@ -929,17 +1176,14 @@
void VisitDoExpression(DoExpression* expr) { UNREACHABLE(); }
- void VisitRewritableAssignmentExpression(
- RewritableAssignmentExpression* expr) {
- UNREACHABLE();
- }
+ void VisitRewritableExpression(RewritableExpression* expr) { UNREACHABLE(); }
struct IndexContainer : public ZoneObject {
uint16_t index;
};
uint16_t LookupOrInsertLocal(Variable* v, LocalType type) {
- DCHECK(current_function_builder_ != nullptr);
+ DCHECK_NOT_NULL(current_function_builder_);
ZoneHashMap::Entry* entry =
local_variables_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
@@ -974,7 +1218,7 @@
}
uint16_t LookupOrInsertFunction(Variable* v) {
- DCHECK(builder_ != nullptr);
+ DCHECK_NOT_NULL(builder_);
ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
uint16_t index = builder_->AddFunction();
@@ -988,11 +1232,11 @@
}
LocalType TypeOf(Expression* expr) {
- DCHECK(expr->bounds().lower == expr->bounds().upper);
+ DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
return TypeFrom(expr->bounds().lower);
}
- LocalType TypeFrom(TypeImpl<ZoneTypeConfig>* type) {
+ LocalType TypeFrom(Type* type) {
if (type->Is(cache_.kAsmInt)) {
return kAstI32;
} else if (type->Is(cache_.kAsmFloat)) {
@@ -1017,10 +1261,14 @@
FunctionLiteral* literal_;
Isolate* isolate_;
Zone* zone_;
+ Handle<Object> foreign_;
TypeCache const& cache_;
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
int block_size_;
- uint16_t init_function_index;
+ uint16_t init_function_index_;
+ uint32_t next_table_index_;
+ ZoneHashMap function_tables_;
+ ImportedFunctionTable imported_function_table_;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
@@ -1029,13 +1277,13 @@
};
AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
- FunctionLiteral* literal)
- : isolate_(isolate), zone_(zone), literal_(literal) {}
+ FunctionLiteral* literal, Handle<Object> foreign)
+ : isolate_(isolate), zone_(zone), literal_(literal), foreign_(foreign) {}
// TODO(aseemgarg): probably should take zone (to write wasm to) as input so
// that zone in constructor may be thrown away once wasm module is written.
WasmModuleIndex* AsmWasmBuilder::Run() {
- AsmWasmBuilderImpl impl(isolate_, zone_, literal_);
+ AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_);
impl.Compile();
WasmModuleWriter* writer = impl.builder_->Build(zone_);
return writer->WriteTo(zone_);