Commit f93066b3 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Remove renumbering of local variables from asm->wasm.

R=ahaas@chromium.org,bradnelson@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/1980543002
Cr-Commit-Position: refs/heads/master@{#36292}
parent 328d6037
......@@ -67,8 +67,9 @@ class AsmWasmBuilderImpl : public AstVisitor {
void InitializeInitFunction() {
init_function_index_ = builder_->AddFunction();
FunctionSig::Builder b(zone(), 0, 0);
current_function_builder_ = builder_->FunctionAt(init_function_index_);
current_function_builder_->ReturnType(kAstStmt);
current_function_builder_->SetSignature(b.Build());
builder_->MarkStartFunction(init_function_index_);
current_function_builder_ = nullptr;
}
......@@ -83,7 +84,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
void VisitFunctionDeclaration(FunctionDeclaration* decl) {
DCHECK_EQ(kModuleScope, scope_);
DCHECK_NULL(current_function_builder_);
uint16_t index = LookupOrInsertFunction(decl->proxy()->var());
uint32_t index = LookupOrInsertFunction(decl->proxy()->var());
current_function_builder_ = builder_->FunctionAt(index);
scope_ = kFuncScope;
RECURSE(Visit(decl->fun()));
......@@ -411,14 +412,19 @@ class AsmWasmBuilderImpl : public AstVisitor {
Scope* scope = expr->scope();
if (scope_ == kFuncScope) {
if (bounds_->get(expr).lower->IsFunction()) {
// Build the signature for the function.
FunctionType* func_type = bounds_->get(expr).lower->AsFunction();
LocalType return_type = TypeFrom(func_type->Result());
current_function_builder_->ReturnType(return_type);
FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
func_type->Arity());
if (return_type != kAstStmt) b.AddReturn(return_type);
for (int i = 0; i < expr->parameter_count(); i++) {
LocalType type = TypeFrom(func_type->Parameter(i));
DCHECK_NE(kAstStmt, type);
LookupOrInsertLocal(scope->parameter(i), type);
b.AddParam(type);
InsertParameter(scope->parameter(i), type, i);
}
current_function_builder_->SetSignature(b.Build());
} else {
UNREACHABLE();
}
......@@ -559,7 +565,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
DCHECK(name->IsPropertyName());
const AstRawString* raw_name = name->AsRawPropertyName();
if (var->is_function()) {
uint16_t index = LookupOrInsertFunction(var);
uint32_t index = LookupOrInsertFunction(var);
builder_->FunctionAt(index)->Exported(1);
builder_->FunctionAt(index)->SetName(
reinterpret_cast<const char*>(raw_name->raw_data()),
......@@ -592,7 +598,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
for (int i = 0; i < func_type->Arity(); i++) {
sig.AddParam(TypeFrom(func_type->Parameter(i)));
}
uint16_t signature_index = builder_->AddSignature(sig.Build());
uint32_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++) {
......@@ -604,11 +610,11 @@ class AsmWasmBuilderImpl : public AstVisitor {
struct FunctionTableIndices : public ZoneObject {
uint32_t start_index;
uint16_t signature_index;
uint32_t signature_index;
};
void InsertFunctionTable(Variable* v, uint32_t start_index,
uint16_t signature_index) {
uint32_t signature_index) {
FunctionTableIndices* container = new (zone()) FunctionTableIndices();
container->start_index = start_index;
container->signature_index = signature_index;
......@@ -652,7 +658,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
entry->value = indices;
}
uint16_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
uint32_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v));
DCHECK_NOT_NULL(entry);
ImportedFunctionIndices* indices =
......@@ -1069,7 +1075,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
case AsmTyper::kMathAbs: {
if (call_type == kAstI32) {
uint16_t tmp = current_function_builder_->AddLocal(kAstI32);
uint32_t tmp = current_function_builder_->AddLocal(kAstI32);
// if set_local(tmp, x) < 0
Visit(call->arguments()->at(0));
......@@ -1104,8 +1110,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
case AsmTyper::kMathMin: {
// TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
if (call_type == kAstI32) {
uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32);
uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32);
uint32_t tmp_x = current_function_builder_->AddLocal(kAstI32);
uint32_t tmp_y = current_function_builder_->AddLocal(kAstI32);
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
......@@ -1139,8 +1145,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
case AsmTyper::kMathMax: {
// TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
if (call_type == kAstI32) {
uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32);
uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32);
uint32_t tmp_x = current_function_builder_->AddLocal(kAstI32);
uint32_t tmp_y = current_function_builder_->AddLocal(kAstI32);
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
......@@ -1247,7 +1253,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
return;
}
}
uint16_t index;
uint32_t index;
VariableProxy* vp = expr->expression()->AsVariableProxy();
if (vp != nullptr &&
Type::Any()->Is(bounds_->get(vp).lower->AsFunction()->Result())) {
......@@ -1628,20 +1634,17 @@ class AsmWasmBuilderImpl : public AstVisitor {
void VisitRewritableExpression(RewritableExpression* expr) { UNREACHABLE(); }
struct IndexContainer : public ZoneObject {
uint16_t index;
uint32_t index;
};
uint16_t LookupOrInsertLocal(Variable* v, LocalType type) {
uint32_t LookupOrInsertLocal(Variable* v, LocalType type) {
DCHECK_NOT_NULL(current_function_builder_);
ZoneHashMap::Entry* entry =
local_variables_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
uint16_t index;
if (v->IsParameter()) {
index = current_function_builder_->AddParam(type);
} else {
index = current_function_builder_->AddLocal(type);
}
uint32_t index;
DCHECK(!v->IsParameter());
index = current_function_builder_->AddLocal(type);
IndexContainer* container = new (zone()) IndexContainer();
container->index = index;
entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
......@@ -1651,11 +1654,24 @@ class AsmWasmBuilderImpl : public AstVisitor {
return (reinterpret_cast<IndexContainer*>(entry->value))->index;
}
uint16_t LookupOrInsertGlobal(Variable* v, LocalType type) {
void InsertParameter(Variable* v, LocalType type, uint32_t index) {
DCHECK(v->IsParameter());
DCHECK_NOT_NULL(current_function_builder_);
ZoneHashMap::Entry* entry =
local_variables_.Lookup(v, ComputePointerHash(v));
DCHECK_NULL(entry);
IndexContainer* container = new (zone()) IndexContainer();
container->index = index;
entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
ZoneAllocationPolicy(zone()));
entry->value = container;
}
uint32_t LookupOrInsertGlobal(Variable* v, LocalType type) {
ZoneHashMap::Entry* entry =
global_variables_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
uint16_t index =
uint32_t index =
builder_->AddGlobal(WasmOpcodes::MachineTypeFor(type), 0);
IndexContainer* container = new (zone()) IndexContainer();
container->index = index;
......@@ -1666,11 +1682,11 @@ class AsmWasmBuilderImpl : public AstVisitor {
return (reinterpret_cast<IndexContainer*>(entry->value))->index;
}
uint16_t LookupOrInsertFunction(Variable* v) {
uint32_t LookupOrInsertFunction(Variable* v) {
DCHECK_NOT_NULL(builder_);
ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
uint16_t index = builder_->AddFunction();
uint32_t index = builder_->AddFunction();
IndexContainer* container = new (zone()) IndexContainer();
container->index = index;
entry = functions_.LookupOrInsert(v, ComputePointerHash(v),
......@@ -1712,7 +1728,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
AsmTyper* typer_;
TypeCache const& cache_;
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
uint16_t init_function_index_;
uint32_t init_function_index_;
uint32_t next_table_index_;
ZoneHashMap function_tables_;
ImportedFunctionTable imported_function_table_;
......
......@@ -95,18 +95,8 @@ byte* EmitSection(WasmSection::Code code, byte** b) {
}
} // namespace
struct WasmFunctionBuilder::Type {
bool param_;
LocalType type_;
};
WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone)
: return_type_(kAstI32),
locals_(zone),
exported_(0),
body_(zone),
local_indices_(zone),
name_(zone) {}
: locals_(zone), exported_(0), body_(zone), name_(zone) {}
void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
byte buffer[8];
......@@ -117,45 +107,28 @@ void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
}
}
uint16_t WasmFunctionBuilder::AddParam(LocalType type) {
return AddVar(type, true);
}
uint16_t WasmFunctionBuilder::AddLocal(LocalType type) {
return AddVar(type, false);
void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
DCHECK(!locals_.has_sig());
locals_.set_sig(sig);
}
uint16_t WasmFunctionBuilder::AddVar(LocalType type, bool param) {
locals_.push_back({param, type});
return static_cast<uint16_t>(locals_.size() - 1);
}
void WasmFunctionBuilder::ReturnType(LocalType type) { return_type_ = type; }
void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
EmitCode(code, code_size, nullptr, 0);
uint32_t WasmFunctionBuilder::AddLocal(LocalType type) {
DCHECK(locals_.has_sig());
return locals_.AddLocals(1, type);
}
void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1));
EmitWithVarInt(kExprGetLocal, local_index);
}
void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1));
EmitWithVarInt(kExprSetLocal, local_index);
}
void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size,
const uint32_t* local_indices,
uint32_t indices_size) {
size_t size = body_.size();
void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
for (size_t i = 0; i < code_size; i++) {
body_.push_back(code[i]);
}
for (size_t i = 0; i < indices_size; i++) {
local_indices_.push_back(local_indices[i] + static_cast<uint32_t>(size));
}
}
void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
......@@ -190,35 +163,6 @@ void WasmFunctionBuilder::EmitI32Const(int32_t value) {
}
}
uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
// Guess that the immediate will be 1 byte. If it is more, we'll have to
// shift everything down.
body_.push_back(0);
return static_cast<uint32_t>(body_.size()) - 1;
}
void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset,
const uint32_t immediate) {
uint32_t immediate_size =
static_cast<uint32_t>(LEBHelper::sizeof_u32v(immediate));
// In EmitEditableVarIntImmediate, we guessed that we'd only need one byte.
// If we need more, shift everything down to make room for the larger
// immediate.
if (immediate_size > 1) {
uint32_t diff = immediate_size - 1;
body_.insert(body_.begin() + offset, diff, 0);
for (size_t i = 0; i < local_indices_.size(); ++i) {
if (local_indices_[i] >= offset) {
local_indices_[i] += diff;
}
}
}
DCHECK(offset + immediate_size <= body_.size());
byte* p = &body_[offset];
v8::internal::wasm::EmitVarInt(&p, immediate);
}
void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
void WasmFunctionBuilder::SetName(const char* name, int name_length) {
......@@ -233,102 +177,17 @@ void WasmFunctionBuilder::SetName(const char* name, int name_length) {
WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
WasmModuleBuilder* mb) const {
WasmFunctionEncoder* e =
new (zone) WasmFunctionEncoder(zone, return_type_, exported_);
uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size());
IndexVars(e, var_index);
if (body_.size() > 0) {
// TODO(titzer): iterate over local indexes, not the bytes.
const byte* start = &body_[0];
size_t local_index = 0;
for (size_t i = 0; i < body_.size();) {
if (local_index < local_indices_.size() &&
i == local_indices_[local_index]) {
// Read the old index.
uint32_t index = 0;
uint8_t b = 0;
uint32_t shift = 0;
while ((b = start[i++]) >= 0x80) {
index |= (b & 0x7F) << shift;
shift += 7;
}
index |= b << shift;
// Write the new index.
uint16_t new_index = var_index[index];
while (new_index >= 0x80) {
e->body_.push_back(new_index | 0x80);
new_index >>= 7;
}
e->body_.push_back(new_index);
local_index++;
} else {
e->body_.push_back(*(start + i));
i++;
}
}
}
FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1,
e->params_.size());
if (return_type_ != kAstStmt) {
sig.AddReturn(static_cast<LocalType>(return_type_));
}
for (size_t i = 0; i < e->params_.size(); i++) {
sig.AddParam(static_cast<LocalType>(e->params_[i]));
}
e->signature_index_ = mb->AddSignature(sig.Build());
new (zone) WasmFunctionEncoder(zone, locals_, exported_);
// TODO(titzer): lame memcpy here.
e->body_.insert(e->body_.begin(), body_.begin(), body_.end());
e->signature_index_ = mb->AddSignature(locals_.get_sig());
e->name_.insert(e->name_.begin(), name_.begin(), name_.end());
return e;
}
void WasmFunctionBuilder::IndexVars(WasmFunctionEncoder* e,
uint16_t* var_index) const {
uint16_t param = 0;
uint16_t i32 = 0;
uint16_t i64 = 0;
uint16_t f32 = 0;
uint16_t f64 = 0;
for (size_t i = 0; i < locals_.size(); i++) {
if (locals_.at(i).param_) {
param++;
} else if (locals_.at(i).type_ == kAstI32) {
i32++;
} else if (locals_.at(i).type_ == kAstI64) {
i64++;
} else if (locals_.at(i).type_ == kAstF32) {
f32++;
} else if (locals_.at(i).type_ == kAstF64) {
f64++;
}
}
e->local_i32_count_ = i32;
e->local_i64_count_ = i64;
e->local_f32_count_ = f32;
e->local_f64_count_ = f64;
f64 = param + i32 + i64 + f32;
f32 = param + i32 + i64;
i64 = param + i32;
i32 = param;
param = 0;
for (size_t i = 0; i < locals_.size(); i++) {
if (locals_.at(i).param_) {
e->params_.push_back(locals_.at(i).type_);
var_index[i] = param++;
} else if (locals_.at(i).type_ == kAstI32) {
var_index[i] = i32++;
} else if (locals_.at(i).type_ == kAstI64) {
var_index[i] = i64++;
} else if (locals_.at(i).type_ == kAstF32) {
var_index[i] = f32++;
} else if (locals_.at(i).type_ == kAstF64) {
var_index[i] = f64++;
}
}
}
WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals,
bool exported)
: params_(zone), exported_(exported), body_(zone), name_(zone) {}
: locals_(locals), exported_(exported), body_(zone), name_(zone) {}
uint32_t WasmFunctionEncoder::HeaderSize() const {
uint32_t size = 3;
......@@ -342,14 +201,7 @@ uint32_t WasmFunctionEncoder::HeaderSize() const {
}
uint32_t WasmFunctionEncoder::BodySize(void) const {
// TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder
LocalDeclEncoder local_decl;
local_decl.AddLocals(local_i32_count_, kAstI32);
local_decl.AddLocals(local_i64_count_, kAstI64);
local_decl.AddLocals(local_f32_count_, kAstF32);
local_decl.AddLocals(local_f64_count_, kAstF64);
return static_cast<uint32_t>(body_.size() + local_decl.Size());
return static_cast<uint32_t>(body_.size() + locals_.Size());
}
uint32_t WasmFunctionEncoder::NameSize() const {
......@@ -371,15 +223,8 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
}
}
// TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder
LocalDeclEncoder local_decl;
local_decl.AddLocals(local_i32_count_, kAstI32);
local_decl.AddLocals(local_i64_count_, kAstI64);
local_decl.AddLocals(local_f32_count_, kAstF32);
local_decl.AddLocals(local_f64_count_, kAstF64);
EmitUint16(header, static_cast<uint16_t>(body_.size() + local_decl.Size()));
(*header) += local_decl.Emit(*header);
EmitUint16(header, static_cast<uint16_t>(body_.size() + locals_.Size()));
(*header) += locals_.Emit(*header);
if (body_.size() > 0) {
std::memcpy(*header, &body_[0], body_.size());
(*header) += body_.size();
......@@ -462,14 +307,14 @@ uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
if (pos != signature_map_.end()) {
return pos->second;
} else {
uint16_t index = static_cast<uint16_t>(signatures_.size());
uint32_t index = static_cast<uint32_t>(signatures_.size());
signature_map_[sig] = index;
signatures_.push_back(sig);
return index;
}
}
void WasmModuleBuilder::AddIndirectFunction(uint16_t index) {
void WasmModuleBuilder::AddIndirectFunction(uint32_t index) {
indirect_functions_.push_back(index);
}
......@@ -479,7 +324,7 @@ uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
return static_cast<uint32_t>(imports_.size() - 1);
}
void WasmModuleBuilder::MarkStartFunction(uint16_t index) {
void WasmModuleBuilder::MarkStartFunction(uint32_t index) {
start_function_index_ = index;
}
......
......@@ -10,6 +10,7 @@
#include "src/base/smart-pointers.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
......@@ -28,14 +29,10 @@ class WasmFunctionEncoder : public ZoneObject {
void Serialize(byte* buffer, byte** header, byte** body) const;
private:
WasmFunctionEncoder(Zone* zone, LocalType return_type, bool exported);
WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals, bool exported);
friend class WasmFunctionBuilder;
uint16_t signature_index_;
ZoneVector<LocalType> params_;
uint16_t local_i32_count_;
uint16_t local_i64_count_;
uint16_t local_f32_count_;
uint16_t local_f64_count_;
uint32_t signature_index_;
LocalDeclEncoder locals_;
bool exported_;
ZoneVector<uint8_t> body_;
ZoneVector<char> name_;
......@@ -45,13 +42,10 @@ class WasmFunctionEncoder : public ZoneObject {
class WasmFunctionBuilder : public ZoneObject {
public:
uint16_t AddParam(LocalType type);
uint16_t AddLocal(LocalType type);
void ReturnType(LocalType type);
void SetSignature(FunctionSig* sig);
uint32_t AddLocal(LocalType type);
void EmitVarInt(uint32_t val);
void EmitCode(const byte* code, uint32_t code_size);
void EmitCode(const byte* code, uint32_t code_size,
const uint32_t* local_indices, uint32_t indices_size);
void Emit(WasmOpcode opcode);
void EmitGetLocal(uint32_t index);
void EmitSetLocal(uint32_t index);
......@@ -59,8 +53,6 @@ class WasmFunctionBuilder : public ZoneObject {
void EmitWithU8(WasmOpcode opcode, const byte immediate);
void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
uint32_t EmitEditableVarIntImmediate();
void EditVarIntImmediate(uint32_t offset, const uint32_t immediate);
void Exported(uint8_t flag);
void SetName(const char* name, int name_length);
WasmFunctionEncoder* Build(Zone* zone, WasmModuleBuilder* mb) const;
......@@ -68,15 +60,11 @@ class WasmFunctionBuilder : public ZoneObject {
private:
explicit WasmFunctionBuilder(Zone* zone);
friend class WasmModuleBuilder;
LocalType return_type_;
struct Type;
ZoneVector<Type> locals_;
LocalDeclEncoder locals_;
uint8_t exported_;
ZoneVector<uint8_t> body_;
ZoneVector<uint32_t> local_indices_;
ZoneVector<char> name_;
uint16_t AddVar(LocalType type, bool param);
void IndexVars(WasmFunctionEncoder* e, uint16_t* var_index) const;
void IndexVars(WasmFunctionEncoder* e, uint32_t* var_index) const;
};
class WasmDataSegmentEncoder : public ZoneObject {
......@@ -122,7 +110,7 @@ class WasmModuleWriter : public ZoneObject {
ZoneVector<WasmFunctionEncoder*> functions_;
ZoneVector<WasmDataSegmentEncoder*> data_segments_;
ZoneVector<FunctionSig*> signatures_;
ZoneVector<uint16_t> indirect_functions_;
ZoneVector<uint32_t> indirect_functions_;
ZoneVector<std::pair<MachineType, bool>> globals_;
int start_function_index_;
};
......@@ -135,15 +123,15 @@ class WasmModuleBuilder : public ZoneObject {
WasmFunctionBuilder* FunctionAt(size_t index);
void AddDataSegment(WasmDataSegmentEncoder* data);
uint32_t AddSignature(FunctionSig* sig);
void AddIndirectFunction(uint16_t index);
void MarkStartFunction(uint16_t index);
void AddIndirectFunction(uint32_t index);
void MarkStartFunction(uint32_t index);
uint32_t AddImport(const char* name, int name_length, FunctionSig* sig);
WasmModuleWriter* Build(Zone* zone);
struct CompareFunctionSigs {
bool operator()(FunctionSig* a, FunctionSig* b) const;
};
typedef ZoneMap<FunctionSig*, uint16_t, CompareFunctionSigs> SignatureMap;
typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap;
private:
Zone* zone_;
......@@ -151,7 +139,7 @@ class WasmModuleBuilder : public ZoneObject {
ZoneVector<WasmFunctionImport> imports_;
ZoneVector<WasmFunctionBuilder*> functions_;
ZoneVector<WasmDataSegmentEncoder*> data_segments_;
ZoneVector<uint16_t> indirect_functions_;
ZoneVector<uint32_t> indirect_functions_;
ZoneVector<std::pair<MachineType, bool>> globals_;
SignatureMap signature_map_;
int start_function_index_;
......
......@@ -7,6 +7,8 @@
#include "src/wasm/wasm-opcodes.h"
#include "src/zone-containers.h"
#define U32_LE(v) \
static_cast<byte>(v), static_cast<byte>((v) >> 8), \
static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
......@@ -130,8 +132,12 @@ inline void CheckI64v(int64_t value, int length) {
// A helper for encoding local declarations prepended to the body of a
// function.
// TODO(titzer): move this to an appropriate header.
class LocalDeclEncoder {
public:
explicit LocalDeclEncoder(Zone* zone, FunctionSig* s = nullptr)
: sig(s), local_decls(zone), total(0) {}
// Prepend local declarations by creating a new buffer and copying data
// over. The new buffer must be delete[]'d by the caller.
void Prepend(const byte** start, const byte** end) const {
......@@ -157,19 +163,16 @@ class LocalDeclEncoder {
// Add locals declarations to this helper. Return the index of the newly added
// local(s), with an optional adjustment for the parameters.
uint32_t AddLocals(uint32_t count, LocalType type,
FunctionSig* sig = nullptr) {
if (count == 0) {
return static_cast<uint32_t>((sig ? sig->parameter_count() : 0) +
local_decls.size());
}
size_t pos = local_decls.size();
uint32_t AddLocals(uint32_t count, LocalType type) {
uint32_t result =
static_cast<uint32_t>(total + (sig ? sig->parameter_count() : 0));
total += count;
if (local_decls.size() > 0 && local_decls.back().second == type) {
count += local_decls.back().first;
local_decls.pop_back();
}
local_decls.push_back(std::pair<uint32_t, LocalType>(count, type));
return static_cast<uint32_t>(pos + (sig ? sig->parameter_count() : 0));
return result;
}
size_t Size() const {
......@@ -178,8 +181,14 @@ class LocalDeclEncoder {
return size;
}
bool has_sig() const { return sig != nullptr; }
FunctionSig* get_sig() const { return sig; }
void set_sig(FunctionSig* s) { sig = s; }
private:
std::vector<std::pair<uint32_t, LocalType>> local_decls;
FunctionSig* sig;
ZoneVector<std::pair<uint32_t, LocalType>> local_decls;
size_t total;
size_t SizeofUint32v(uint32_t val) const {
size_t size = 1;
......
......@@ -12,6 +12,7 @@
#include "src/wasm/wasm-opcodes.h"
#include "test/cctest/cctest.h"
#include "test/cctest/wasm/test-signatures.h"
using namespace v8::base;
using namespace v8::internal;
......@@ -31,12 +32,14 @@ void TestModule(WasmModuleIndex* module, int32_t expected_result) {
TEST(Run_WasmModule_Return114) {
static const int32_t kReturnValue = 114;
TestSignatures sigs;
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
f->Exported(1);
byte code[] = {WASM_I8(kReturnValue)};
f->EmitCode(code, sizeof(code));
......@@ -47,17 +50,22 @@ TEST(Run_WasmModule_Return114) {
TEST(Run_WasmModule_CallAdd) {
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f1_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
f->ReturnType(kAstI32);
uint16_t param1 = f->AddParam(kAstI32);
uint16_t param2 = f->AddParam(kAstI32);
f->SetSignature(sigs.i_ii());
uint16_t param1 = 0;
uint16_t param2 = 1;
byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
f->EmitCode(code1, sizeof(code1));
uint16_t f2_index = builder->AddFunction();
f = builder->FunctionAt(f2_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
f->Exported(1);
byte code2[] = {WASM_CALL_FUNCTION2(f1_index, WASM_I8(77), WASM_I8(22))};
f->EmitCode(code2, sizeof(code2));
......@@ -69,10 +77,13 @@ TEST(Run_WasmModule_ReadLoadedDataSegment) {
static const byte kDataSegmentDest0 = 12;
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
f->Exported(1);
byte code[] = {
WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))};
......@@ -88,10 +99,13 @@ TEST(Run_WasmModule_CheckMemoryIsZero) {
static const int kCheckSize = 16 * 1024;
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
uint16_t localIndex = f->AddLocal(kAstI32);
f->Exported(1);
byte code[] = {WASM_BLOCK(
......@@ -102,7 +116,7 @@ TEST(Run_WasmModule_CheckMemoryIsZero) {
WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)),
WASM_BRV(2, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))),
WASM_I8(11))};
f->EmitCode(code, sizeof(code), nullptr, 0);
f->EmitCode(code, sizeof(code));
WasmModuleWriter* writer = builder->Build(&zone);
TestModule(writer->WriteTo(&zone), 11);
}
......@@ -110,10 +124,13 @@ TEST(Run_WasmModule_CheckMemoryIsZero) {
TEST(Run_WasmModule_CallMain_recursive) {
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
uint16_t localIndex = f->AddLocal(kAstI32);
f->Exported(1);
byte code[] = {WASM_BLOCK(
......@@ -124,7 +141,7 @@ TEST(Run_WasmModule_CallMain_recursive) {
WASM_INC_LOCAL(localIndex)),
WASM_BRV(1, WASM_CALL_FUNCTION0(0))),
WASM_BRV(0, WASM_I8(55))))};
f->EmitCode(code, sizeof(code), nullptr, 0);
f->EmitCode(code, sizeof(code));
WasmModuleWriter* writer = builder->Build(&zone);
TestModule(writer->WriteTo(&zone), 55);
}
......@@ -132,18 +149,20 @@ TEST(Run_WasmModule_CallMain_recursive) {
TEST(Run_WasmModule_Global) {
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint32_t global1 = builder->AddGlobal(MachineType::Int32(), 0);
uint32_t global2 = builder->AddGlobal(MachineType::Int32(), 0);
uint16_t f1_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
byte code1[] = {
WASM_I32_ADD(WASM_LOAD_GLOBAL(global1), WASM_LOAD_GLOBAL(global2))};
f->EmitCode(code1, sizeof(code1));
uint16_t f2_index = builder->AddFunction();
f = builder->FunctionAt(f2_index);
f->ReturnType(kAstI32);
f->SetSignature(sigs.i_v());
f->Exported(1);
byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32V_1(56)),
WASM_STORE_GLOBAL(global2, WASM_I32V_1(41)),
......
......@@ -422,6 +422,7 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
descriptor_(nullptr),
testing_module_(module),
debug_name_(debug_name),
local_decls(main_zone(), sig),
source_position_table_(this->graph()) {
if (module) {
// Get a new function from the testing module.
......@@ -471,7 +472,7 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
}
byte AllocateLocal(LocalType type) {
uint32_t index = local_decls.AddLocals(1, type, sig);
uint32_t index = local_decls.AddLocals(1, type);
byte result = static_cast<byte>(index);
DCHECK_EQ(index, result);
return result;
......
......@@ -68,7 +68,8 @@ class AstDecoderTest : public TestWithZone {
public:
typedef std::pair<uint32_t, LocalType> LocalsDecl;
AstDecoderTest() : module(nullptr) {}
AstDecoderTest() : module(nullptr), local_decls(zone()) {}
TestSignatures sigs;
ModuleEnv* module;
LocalDeclEncoder local_decls;
......@@ -2421,7 +2422,7 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) {
TEST_F(LocalDeclDecoderTest, UseEncoder) {
const byte* data = nullptr;
const byte* end = nullptr;
LocalDeclEncoder local_decls;
LocalDeclEncoder local_decls(zone());
local_decls.AddLocals(5, kAstF32);
local_decls.AddLocals(1337, kAstI32);
......
......@@ -9,6 +9,8 @@
#include "src/wasm/ast-decoder.h"
#include "src/wasm/encoder.h"
#include "test/cctest/wasm/test-signatures.h"
namespace v8 {
namespace internal {
namespace wasm {
......@@ -21,141 +23,6 @@ class EncoderTest : public TestWithZone {
}
};
TEST_F(EncoderTest, Function_Builder_Variable_Indexing) {
base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
uint16_t local_f32 = function->AddLocal(kAstF32);
uint16_t param_float32 = function->AddParam(kAstF32);
uint16_t local_i32 = function->AddLocal(kAstI32);
uint16_t local_f64 = function->AddLocal(kAstF64);
uint16_t local_i64 = function->AddLocal(kAstI64);
uint16_t param_int32 = function->AddParam(kAstI32);
uint16_t local_i32_2 = function->AddLocal(kAstI32);
byte code[] = {kExprGetLocal, static_cast<uint8_t>(param_float32)};
uint32_t local_indices[] = {1};
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(param_int32);
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(local_i32);
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(local_i32_2);
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(local_i64);
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(local_f32);
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(local_f64);
function->EmitCode(code, sizeof(code), local_indices, 1);
WasmFunctionEncoder* f = function->Build(&zone, builder);
ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
byte* buffer = &buffer_vector[0];
byte* header = buffer;
byte* body = buffer + f->HeaderSize();
f->Serialize(buffer, &header, &body);
}
TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) {
base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
for (size_t i = 0; i < 128; i++) {
AddLocal(function, kAstF32);
}
AddLocal(function, kAstI32);
WasmFunctionEncoder* f = function->Build(&zone, builder);
ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
byte* buffer = &buffer_vector[0];
byte* header = buffer;
byte* body = buffer + f->HeaderSize();
f->Serialize(buffer, &header, &body);
body = buffer + f->HeaderSize();
}
TEST_F(EncoderTest, Function_Builder_Block_Variable_Width) {
base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
function->EmitWithVarInt(kExprBlock, 200);
for (int i = 0; i < 200; ++i) {
function->Emit(kExprNop);
}
WasmFunctionEncoder* f = function->Build(&zone, builder);
CHECK_EQ(f->BodySize(), 204);
}
TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate) {
base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
function->Emit(kExprLoop);
uint32_t offset = function->EmitEditableVarIntImmediate();
for (int i = 0; i < 200; ++i) {
function->Emit(kExprNop);
}
function->EditVarIntImmediate(offset, 200);
WasmFunctionEncoder* f = function->Build(&zone, builder);
CHECK_EQ(f->BodySize(), 204);
}
TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate_Locals) {
base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
function->Emit(kExprBlock);
uint32_t offset = function->EmitEditableVarIntImmediate();
for (int i = 0; i < 200; ++i) {
AddLocal(function, kAstI32);
}
function->EditVarIntImmediate(offset, 200);
WasmFunctionEncoder* f = function->Build(&zone, builder);
ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
byte* buffer = &buffer_vector[0];
byte* header = buffer;
byte* body = buffer + f->HeaderSize();
f->Serialize(buffer, &header, &body);
body = buffer + f->HeaderSize();
CHECK_EQ(f->BodySize(), 479);
const uint8_t varint200_low = (200 & 0x7f) | 0x80;
const uint8_t varint200_high = (200 >> 7) & 0x7f;
offset = 0;
CHECK_EQ(body[offset++], 1); // Local decl count.
CHECK_EQ(body[offset++], varint200_low);
CHECK_EQ(body[offset++], varint200_high);
CHECK_EQ(body[offset++], kLocalI32);
CHECK_EQ(body[offset++], kExprBlock);
CHECK_EQ(body[offset++], varint200_low);
CHECK_EQ(body[offset++], varint200_high);
// GetLocal with one-byte indices.
for (int i = 0; i <= 127; ++i) {
CHECK_EQ(body[offset++], kExprGetLocal);
CHECK_EQ(body[offset++], i);
}
// GetLocal with two-byte indices.
for (int i = 128; i < 200; ++i) {
CHECK_EQ(body[offset++], kExprGetLocal);
CHECK_EQ(body[offset++], (i & 0x7f) | 0x80);
CHECK_EQ(body[offset++], (i >> 7) & 0x7f);
}
CHECK_EQ(offset, 479);
}
} // namespace wasm
} // namespace internal
} // namespace v8
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