Commit 835c5e6b authored by titzer's avatar titzer Committed by Commit bot

[wasm] Rework encoding of local declarations.

Local declarations were previously encoded as an optional set of
4 uint16 values as part of the function declaration. This CL
implements the current design of moving these declarations to
a list of pairs of (type, count) that is part of the body.

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

Review URL: https://codereview.chromium.org/1763433002

Cr-Commit-Position: refs/heads/master@{#34564}
parent 826f67be
...@@ -2409,15 +2409,6 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, ...@@ -2409,15 +2409,6 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
<< wasm::WasmFunctionName(&function, module_env) << std::endl; << wasm::WasmFunctionName(&function, module_env) << std::endl;
os << std::endl; os << std::endl;
} }
// Initialize the function environment for decoding.
wasm::FunctionEnv env;
env.module = module_env;
env.sig = function.sig;
env.local_i32_count = function.local_i32_count;
env.local_i64_count = function.local_i64_count;
env.local_f32_count = function.local_f32_count;
env.local_f64_count = function.local_f64_count;
env.SumLocals();
// Create a TF graph during decoding. // Create a TF graph during decoding.
Zone zone; Zone zone;
...@@ -2428,11 +2419,11 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, ...@@ -2428,11 +2419,11 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
InstructionSelector::SupportedMachineOperatorFlags()); InstructionSelector::SupportedMachineOperatorFlags());
JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
WasmGraphBuilder builder(&zone, &jsgraph, function.sig); WasmGraphBuilder builder(&zone, &jsgraph, function.sig);
wasm::TreeResult result = wasm::BuildTFGraph( wasm::FunctionBody body = {
&builder, &env, // -- module_env, function.sig, module_env->module->module_start,
module_env->module->module_start, // -- module_env->module->module_start + function.code_start_offset,
module_env->module->module_start + function.code_start_offset, // -- module_env->module->module_start + function.code_end_offset};
module_env->module->module_start + function.code_end_offset); // -- wasm::TreeResult result = wasm::BuildTFGraph(&builder, body);
if (result.failed()) { if (result.failed()) {
if (FLAG_trace_wasm_compiler) { if (FLAG_trace_wasm_compiler) {
......
This diff is collapsed.
...@@ -183,61 +183,13 @@ struct MemoryAccessOperand { ...@@ -183,61 +183,13 @@ struct MemoryAccessOperand {
typedef compiler::WasmGraphBuilder TFBuilder; typedef compiler::WasmGraphBuilder TFBuilder;
struct ModuleEnv; // forward declaration of module interface. struct ModuleEnv; // forward declaration of module interface.
// Interface the function environment during decoding, include the signature // All of the various data structures necessary to decode a function body.
// and number of locals. struct FunctionBody {
struct FunctionEnv { ModuleEnv* module; // module environment
ModuleEnv* module; // module environment FunctionSig* sig; // function signature
FunctionSig* sig; // signature of this function const byte* base; // base of the module bytes, for error reporting
uint32_t local_i32_count; // number of int32 locals const byte* start; // start of the function body
uint32_t local_i64_count; // number of int64 locals const byte* end; // end of the function body
uint32_t local_f32_count; // number of float32 locals
uint32_t local_f64_count; // number of float64 locals
uint32_t total_locals; // sum of parameters and all locals
uint32_t GetLocalCount() { return total_locals; }
LocalType GetLocalType(uint32_t index) {
if (index < static_cast<uint32_t>(sig->parameter_count())) {
return sig->GetParam(index);
}
index -= static_cast<uint32_t>(sig->parameter_count());
if (index < local_i32_count) return kAstI32;
index -= local_i32_count;
if (index < local_i64_count) return kAstI64;
index -= local_i64_count;
if (index < local_f32_count) return kAstF32;
index -= local_f32_count;
if (index < local_f64_count) return kAstF64;
return kAstStmt;
}
void AddLocals(LocalType type, uint32_t count) {
switch (type) {
case kAstI32:
local_i32_count += count;
break;
case kAstI64:
local_i64_count += count;
break;
case kAstF32:
local_f32_count += count;
break;
case kAstF64:
local_f64_count += count;
break;
default:
UNREACHABLE();
}
total_locals += count;
DCHECK_EQ(total_locals,
(sig->parameter_count() + local_i32_count + local_i64_count +
local_f32_count + local_f64_count));
}
void SumLocals() {
total_locals = static_cast<uint32_t>(sig->parameter_count()) +
local_i32_count + local_i64_count + local_f32_count +
local_f64_count;
}
}; };
struct Tree; struct Tree;
...@@ -245,21 +197,21 @@ typedef Result<Tree*> TreeResult; ...@@ -245,21 +197,21 @@ typedef Result<Tree*> TreeResult;
std::ostream& operator<<(std::ostream& os, const Tree& tree); std::ostream& operator<<(std::ostream& os, const Tree& tree);
TreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start, TreeResult VerifyWasmCode(FunctionBody& body);
const byte* end); TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body);
TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base, void PrintAst(FunctionBody& body);
const byte* start, const byte* end);
void PrintAst(FunctionEnv* env, const byte* start, const byte* end);
inline TreeResult VerifyWasmCode(FunctionEnv* env, const byte* start, inline TreeResult VerifyWasmCode(ModuleEnv* module, FunctionSig* sig,
const byte* end) { const byte* start, const byte* end) {
return VerifyWasmCode(env, nullptr, start, end); FunctionBody body = {module, sig, nullptr, start, end};
return VerifyWasmCode(body);
} }
inline TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, inline TreeResult BuildTFGraph(TFBuilder* builder, ModuleEnv* module,
const byte* start, const byte* end) { FunctionSig* sig, const byte* start,
return BuildTFGraph(builder, env, nullptr, start, end); const byte* end) {
FunctionBody body = {module, sig, nullptr, start, end};
return BuildTFGraph(builder, body);
} }
enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 }; enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
...@@ -267,14 +219,17 @@ enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 }; ...@@ -267,14 +219,17 @@ enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*, ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*,
int*, uint32_t*); int*, uint32_t*);
BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, FunctionEnv* env, std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start,
const byte* end);
BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end); const byte* start, const byte* end);
// Computes the length of the opcode at the given address. // Computes the length of the opcode at the given address.
int OpcodeLength(const byte* pc, const byte* end); int OpcodeLength(const byte* pc, const byte* end);
// Computes the arity (number of sub-nodes) of the opcode at the given address. // Computes the arity (number of sub-nodes) of the opcode at the given address.
int OpcodeArity(FunctionEnv* env, const byte* pc, const byte* end); int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
const byte* end);
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -327,6 +327,7 @@ class Decoder { ...@@ -327,6 +327,7 @@ class Decoder {
bool ok() const { return error_pc_ == nullptr; } bool ok() const { return error_pc_ == nullptr; }
bool failed() const { return error_pc_ != nullptr; } bool failed() const { return error_pc_ != nullptr; }
bool more() const { return pc_ < limit_; }
const byte* start() { return start_; } const byte* start() { return start_; }
const byte* pc() { return pc_; } const byte* pc() { return pc_; }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/wasm/ast-decoder.h" #include "src/wasm/ast-decoder.h"
#include "src/wasm/encoder.h" #include "src/wasm/encoder.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h" #include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h" #include "src/wasm/wasm-opcodes.h"
...@@ -250,7 +251,6 @@ WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type, ...@@ -250,7 +251,6 @@ WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
uint32_t WasmFunctionEncoder::HeaderSize() const { uint32_t WasmFunctionEncoder::HeaderSize() const {
uint32_t size = 3; uint32_t size = 3;
if (HasLocals()) size += 8;
if (!external_) size += 2; if (!external_) size += 2;
if (HasName()) size += 4; if (HasName()) size += 4;
return size; return size;
...@@ -258,7 +258,15 @@ uint32_t WasmFunctionEncoder::HeaderSize() const { ...@@ -258,7 +258,15 @@ uint32_t WasmFunctionEncoder::HeaderSize() const {
uint32_t WasmFunctionEncoder::BodySize(void) const { uint32_t WasmFunctionEncoder::BodySize(void) const {
return external_ ? 0 : static_cast<uint32_t>(body_.size()); // 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 external_ ? 0
: static_cast<uint32_t>(body_.size() + local_decl.Size());
} }
...@@ -271,7 +279,6 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header, ...@@ -271,7 +279,6 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
byte** body) const { byte** body) const {
uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) | uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) |
(external_ ? kDeclFunctionImport : 0) | (external_ ? kDeclFunctionImport : 0) |
(HasLocals() ? kDeclFunctionLocals : 0) |
(HasName() ? kDeclFunctionName : 0); (HasName() ? kDeclFunctionName : 0);
EmitUint8(header, decl_bits); EmitUint8(header, decl_bits);
...@@ -284,15 +291,17 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header, ...@@ -284,15 +291,17 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
(*body) += name_.size(); (*body) += name_.size();
} }
if (HasLocals()) {
EmitUint16(header, local_i32_count_);
EmitUint16(header, local_i64_count_);
EmitUint16(header, local_f32_count_);
EmitUint16(header, local_f64_count_);
}
if (!external_) { if (!external_) {
EmitUint16(header, static_cast<uint16_t>(body_.size())); // 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);
if (body_.size() > 0) { if (body_.size() > 0) {
std::memcpy(*header, &body_[0], body_.size()); std::memcpy(*header, &body_[0], body_.size());
(*header) += body_.size(); (*header) += body_.size();
......
...@@ -42,11 +42,6 @@ class WasmFunctionEncoder : public ZoneObject { ...@@ -42,11 +42,6 @@ class WasmFunctionEncoder : public ZoneObject {
ZoneVector<uint8_t> body_; ZoneVector<uint8_t> body_;
ZoneVector<char> name_; ZoneVector<char> name_;
bool HasLocals() const {
return (local_i32_count_ + local_i64_count_ + local_f32_count_ +
local_f64_count_) > 0;
}
bool HasName() const { return (exported_ || external_) && name_.size() > 0; } bool HasName() const { return (exported_ || external_) && name_.size() > 0; }
}; };
......
...@@ -338,14 +338,10 @@ class ModuleDecoder : public Decoder { ...@@ -338,14 +338,10 @@ class ModuleDecoder : public Decoder {
FunctionResult DecodeSingleFunction(ModuleEnv* module_env, FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
WasmFunction* function) { WasmFunction* function) {
pc_ = start_; pc_ = start_;
function->sig = consume_sig(); // read signature function->sig = consume_sig(); // read signature
function->name_offset = 0; // ---- name function->name_offset = 0; // ---- name
function->code_start_offset = off(pc_ + 8); // ---- code start function->code_start_offset = off(pc_); // ---- code start
function->code_end_offset = off(limit_); // ---- code end function->code_end_offset = off(limit_); // ---- code end
function->local_i32_count = consume_u16(); // read u16
function->local_i64_count = consume_u16(); // read u16
function->local_f32_count = consume_u16(); // read u16
function->local_f64_count = consume_u16(); // read u16
function->exported = false; // ---- exported function->exported = false; // ---- exported
function->external = false; // ---- external function->external = false; // ---- external
...@@ -473,18 +469,10 @@ class ModuleDecoder : public Decoder { ...@@ -473,18 +469,10 @@ class ModuleDecoder : public Decoder {
<< std::endl; << std::endl;
os << std::endl; os << std::endl;
} }
FunctionEnv fenv; FunctionBody body = {menv, function->sig, start_,
fenv.module = menv; start_ + function->code_start_offset,
fenv.sig = function->sig; start_ + function->code_end_offset};
fenv.local_i32_count = function->local_i32_count; TreeResult result = VerifyWasmCode(body);
fenv.local_i64_count = function->local_i64_count;
fenv.local_f32_count = function->local_f32_count;
fenv.local_f64_count = function->local_f64_count;
fenv.SumLocals();
TreeResult result =
VerifyWasmCode(&fenv, start_, start_ + function->code_start_offset,
start_ + function->code_end_offset);
if (result.failed()) { if (result.failed()) {
// Wrap the error message from the function decoder. // Wrap the error message from the function decoder.
std::ostringstream str; std::ostringstream str;
......
...@@ -7,6 +7,43 @@ ...@@ -7,6 +7,43 @@
#include "src/wasm/wasm-opcodes.h" #include "src/wasm/wasm-opcodes.h"
#define U32_LE(v) \
static_cast<byte>(v), static_cast<byte>((v) >> 8), \
static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
#define U16_LE(v) static_cast<byte>(v), static_cast<byte>((v) >> 8)
#define WASM_MODULE_HEADER U32_LE(kWasmMagic), U32_LE(kWasmVersion)
#define SIG_INDEX(v) U16_LE(v)
#define FUNC_INDEX(v) U16_LE(v)
#define NAME_OFFSET(v) U32_LE(v)
#define BR_TARGET(v) U16_LE(v)
#define MASK_7 ((1 << 7) - 1)
#define MASK_14 ((1 << 14) - 1)
#define MASK_21 ((1 << 21) - 1)
#define MASK_28 ((1 << 28) - 1)
#define U32V_1(x) static_cast<byte>((x)&MASK_7)
#define U32V_2(x) \
static_cast<byte>(((x)&MASK_7) | 0x80), static_cast<byte>(((x) >> 7) & MASK_7)
#define U32V_3(x) \
static_cast<byte>((((x)) & MASK_7) | 0x80), \
static_cast<byte>((((x) >> 7) & MASK_7) | 0x80), \
static_cast<byte>(((x) >> 14) & MASK_7)
#define U32V_4(x) \
static_cast<byte>(((x)&MASK_7) | 0x80), \
static_cast<byte>((((x) >> 7) & MASK_7) | 0x80), \
static_cast<byte>((((x) >> 14) & MASK_7) | 0x80), \
static_cast<byte>(((x) >> 21) & MASK_7)
#define U32V_5(x) \
static_cast<byte>(((x)&MASK_7) | 0x80), \
static_cast<byte>((((x) >> 7) & MASK_7) | 0x80), \
static_cast<byte>((((x) >> 14) & MASK_7) | 0x80), \
static_cast<byte>((((x) >> 21) & MASK_7) | 0x80), \
static_cast<byte>((((x) >> 28) & MASK_7))
// Convenience macros for building Wasm bytecode directly into a byte array. // Convenience macros for building Wasm bytecode directly into a byte array.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -57,6 +94,8 @@ ...@@ -57,6 +94,8 @@
#define I64V_IN_RANGE(value, length) \ #define I64V_IN_RANGE(value, length) \
((value) >= I64V_MIN(length) && (value) <= I64V_MAX(length)) ((value) >= I64V_MIN(length) && (value) <= I64V_MAX(length))
#define WASM_NO_LOCALS 0
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
...@@ -73,6 +112,83 @@ inline void CheckI64v(int64_t value, int length) { ...@@ -73,6 +112,83 @@ inline void CheckI64v(int64_t value, int length) {
DCHECK(length == 1 || !I64V_IN_RANGE(value, length - 1)); DCHECK(length == 1 || !I64V_IN_RANGE(value, length - 1));
} }
// A helper for encoding local declarations prepended to the body of a
// function.
class LocalDeclEncoder {
public:
// 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 {
size_t size = (*end - *start);
byte* buffer = new byte[Size() + size];
size_t pos = Emit(buffer);
memcpy(buffer + pos, *start, size);
pos += size;
*start = buffer;
*end = buffer + pos;
}
size_t Emit(byte* buffer) const {
size_t pos = 0;
pos = WriteUint32v(buffer, pos, static_cast<uint32_t>(local_decls.size()));
for (size_t i = 0; i < local_decls.size(); i++) {
pos = WriteUint32v(buffer, pos, local_decls[i].first);
buffer[pos++] = WasmOpcodes::LocalTypeCodeFor(local_decls[i].second);
}
DCHECK_EQ(Size(), pos);
return pos;
}
// 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();
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));
}
size_t Size() const {
size_t size = SizeofUint32v(static_cast<uint32_t>(local_decls.size()));
for (auto p : local_decls) size += 1 + SizeofUint32v(p.first);
return size;
}
private:
std::vector<std::pair<uint32_t, LocalType>> local_decls;
size_t SizeofUint32v(uint32_t val) const {
size_t size = 1;
while (true) {
byte b = val & MASK_7;
if (b == val) return size;
size++;
val = val >> 7;
}
}
// TODO(titzer): lift encoding of u32v to a common place.
size_t WriteUint32v(byte* buffer, size_t pos, uint32_t val) const {
while (true) {
byte b = val & MASK_7;
if (b == val) {
buffer[pos++] = b;
break;
}
buffer[pos++] = 0x80 | b;
val = val >> 7;
}
return pos;
}
};
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -390,41 +506,4 @@ inline void CheckI64v(int64_t value, int length) { ...@@ -390,41 +506,4 @@ inline void CheckI64v(int64_t value, int length) {
#define WASM_I32_REINTERPRET_F32(x) kExprI32ReinterpretF32, x #define WASM_I32_REINTERPRET_F32(x) kExprI32ReinterpretF32, x
#define WASM_I64_REINTERPRET_F64(x) kExprI64ReinterpretF64, x #define WASM_I64_REINTERPRET_F64(x) kExprI64ReinterpretF64, x
#define U32_LE(v) \
static_cast<byte>(v), static_cast<byte>((v) >> 8), \
static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
#define U16_LE(v) static_cast<byte>(v), static_cast<byte>((v) >> 8)
#define WASM_MODULE_HEADER U32_LE(kWasmMagic), U32_LE(kWasmVersion)
#define SIG_INDEX(v) U16_LE(v)
#define FUNC_INDEX(v) U16_LE(v)
#define NAME_OFFSET(v) U32_LE(v)
#define BR_TARGET(v) U16_LE(v)
#define MASK_7 ((1 << 7) - 1)
#define MASK_14 ((1 << 14) - 1)
#define MASK_21 ((1 << 21) - 1)
#define MASK_28 ((1 << 28) - 1)
#define U32V_1(x) static_cast<byte>(x & MASK_7)
#define U32V_2(x) \
static_cast<byte>((x & MASK_7) | 0x80), static_cast<byte>((x >> 7) & MASK_7)
#define U32V_3(x) \
static_cast<byte>((x & MASK_7) | 0x80), \
static_cast<byte>(((x >> 7) & MASK_7) | 0x80), \
static_cast<byte>((x >> 14) & MASK_7)
#define U32V_4(x) \
static_cast<byte>((x & MASK_7) | 0x80), \
static_cast<byte>(((x >> 7) & MASK_7) | 0x80), \
static_cast<byte>(((x >> 14) & MASK_7) | 0x80), \
static_cast<byte>((x >> 21) & MASK_7)
#define U32V_5(x) \
static_cast<byte>((x & MASK_7) | 0x80), \
static_cast<byte>(((x >> 7) & MASK_7) | 0x80), \
static_cast<byte>(((x >> 14) & MASK_7) | 0x80), \
static_cast<byte>(((x >> 21) & MASK_7) | 0x80), \
static_cast<byte>(((x >> 28) & MASK_7))
#endif // V8_WASM_MACRO_GEN_H_ #endif // V8_WASM_MACRO_GEN_H_
...@@ -97,7 +97,8 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function); ...@@ -97,7 +97,8 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
V(StoreGlobal, 0x11, _) \ V(StoreGlobal, 0x11, _) \
V(CallFunction, 0x12, _) \ V(CallFunction, 0x12, _) \
V(CallIndirect, 0x13, _) \ V(CallIndirect, 0x13, _) \
V(CallImport, 0x1F, _) V(CallImport, 0x1F, _) \
V(DeclLocals, 0x1E, _)
// Load memory expressions. // Load memory expressions.
#define FOREACH_LOAD_MEM_OPCODE(V) \ #define FOREACH_LOAD_MEM_OPCODE(V) \
......
...@@ -206,8 +206,7 @@ TEST(Run_WasmCallI64Parameter) { ...@@ -206,8 +206,7 @@ TEST(Run_WasmCallI64Parameter) {
uint32_t index = t.CompileAndAdd(); uint32_t index = t.CompileAndAdd();
// Build the calling function. // Build the calling function.
WasmRunner<int32_t> r; WasmRunner<int32_t> r(&module);
r.env()->module = &module;
BUILD( BUILD(
r, r,
WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION( WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
......
...@@ -42,14 +42,16 @@ TEST(Run_WasmModule_CallAdd_rev) { ...@@ -42,14 +42,16 @@ TEST(Run_WasmModule_CallAdd_rev) {
2, kLocalI32, kLocalI32, kLocalI32, // int,int -> int 2, kLocalI32, kLocalI32, kLocalI32, // int,int -> int
// func#0 (main) ---------------------------------- // func#0 (main) ----------------------------------
kDeclFunctions, 2, kDeclFunctionExport, 0, 0, // sig index kDeclFunctions, 2, kDeclFunctionExport, 0, 0, // sig index
6, 0, // body size 7, 0, // body size
0, // locals
kExprCallFunction, 1, // -- kExprCallFunction, 1, // --
kExprI8Const, 77, // -- kExprI8Const, 77, // --
kExprI8Const, 22, // -- kExprI8Const, 22, // --
// func#1 ----------------------------------------- // func#1 -----------------------------------------
0, // no name, not exported 0, // no name, not exported
1, 0, // sig index 1, 0, // sig index
5, 0, // body size 6, 0, // body size
0, // locals
kExprI32Add, // -- kExprI32Add, // --
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
......
...@@ -973,7 +973,8 @@ TEST(Run_Wasm_Select_strict1) { ...@@ -973,7 +973,8 @@ TEST(Run_Wasm_Select_strict1) {
TEST(Run_Wasm_Select_strict2) { TEST(Run_Wasm_Select_strict2) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
r.env()->AddLocals(kAstI32, 2); r.AllocateLocal(kAstI32);
r.AllocateLocal(kAstI32);
// select(b=5, c=6, a) // select(b=5, c=6, a)
BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)), BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
WASM_SET_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0))); WASM_SET_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0)));
...@@ -985,7 +986,8 @@ TEST(Run_Wasm_Select_strict2) { ...@@ -985,7 +986,8 @@ TEST(Run_Wasm_Select_strict2) {
TEST(Run_Wasm_Select_strict3) { TEST(Run_Wasm_Select_strict3) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
r.env()->AddLocals(kAstI32, 2); r.AllocateLocal(kAstI32);
r.AllocateLocal(kAstI32);
// select(b=5, c=6, a=b) // select(b=5, c=6, a=b)
BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)), BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
WASM_SET_LOCAL(2, WASM_I8(6)), WASM_SET_LOCAL(2, WASM_I8(6)),
...@@ -1232,8 +1234,7 @@ TEST(Run_Wasm_VoidReturn1) { ...@@ -1232,8 +1234,7 @@ TEST(Run_Wasm_VoidReturn1) {
const int32_t kExpected = -414444; const int32_t kExpected = -414444;
// Build the calling function. // Build the calling function.
WasmRunner<int32_t> r; WasmRunner<int32_t> r(&module);
r.env()->module = &module;
BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected)));
int32_t result = r.Call(); int32_t result = r.Call();
...@@ -1252,8 +1253,7 @@ TEST(Run_Wasm_VoidReturn2) { ...@@ -1252,8 +1253,7 @@ TEST(Run_Wasm_VoidReturn2) {
const int32_t kExpected = -414444; const int32_t kExpected = -414444;
// Build the calling function. // Build the calling function.
WasmRunner<int32_t> r; WasmRunner<int32_t> r(&module);
r.env()->module = &module;
BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected)));
int32_t result = r.Call(); int32_t result = r.Call();
...@@ -2006,18 +2006,19 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) { ...@@ -2006,18 +2006,19 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
MachineOperatorBuilder::kAllOptionalOps); MachineOperatorBuilder::kAllOptionalOps);
Graph graph(&zone); Graph graph(&zone);
JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
FunctionEnv env;
FunctionSig* sig = WasmOpcodes::Signature(opcode); FunctionSig* sig = WasmOpcodes::Signature(opcode);
init_env(&env, sig);
if (sig->parameter_count() == 1) { if (sig->parameter_count() == 1) {
byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0}; byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode), kExprGetLocal, 0};
TestBuildingGraph(&zone, &jsgraph, &env, code, code + arraysize(code)); TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
code + arraysize(code));
} else { } else {
CHECK_EQ(2, sig->parameter_count()); CHECK_EQ(2, sig->parameter_count());
byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0, kExprGetLocal, byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode),
1}; kExprGetLocal, 0,
TestBuildingGraph(&zone, &jsgraph, &env, code, code + arraysize(code)); kExprGetLocal, 1};
TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
code + arraysize(code));
} }
} }
......
...@@ -63,16 +63,6 @@ using namespace v8::internal; ...@@ -63,16 +63,6 @@ using namespace v8::internal;
using namespace v8::internal::compiler; using namespace v8::internal::compiler;
using namespace v8::internal::wasm; using namespace v8::internal::wasm;
inline void init_env(FunctionEnv* env, FunctionSig* sig) {
env->module = nullptr;
env->sig = sig;
env->local_i32_count = 0;
env->local_i64_count = 0;
env->local_f32_count = 0;
env->local_f64_count = 0;
env->SumLocals();
}
const uint32_t kMaxGlobalsSize = 128; const uint32_t kMaxGlobalsSize = 128;
// A helper for module environments that adds the ability to allocate memory // A helper for module environments that adds the ability to allocate memory
...@@ -227,11 +217,11 @@ class TestingModule : public ModuleEnv { ...@@ -227,11 +217,11 @@ class TestingModule : public ModuleEnv {
} }
}; };
inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, FunctionEnv* env, FunctionSig* sig, const byte* start,
const byte* start, const byte* end) { const byte* end) {
compiler::WasmGraphBuilder builder(zone, jsgraph, env->sig); compiler::WasmGraphBuilder builder(zone, jsgraph, sig);
TreeResult result = BuildTFGraph(&builder, env, start, end); TreeResult result = BuildTFGraph(&builder, module, sig, start, end);
if (result.failed()) { if (result.failed()) {
ptrdiff_t pc = result.error_pc - result.start; ptrdiff_t pc = result.error_pc - result.start;
ptrdiff_t pt = result.error_pt - result.start; ptrdiff_t pt = result.error_pt - result.start;
...@@ -399,10 +389,9 @@ class WasmFunctionCompiler : public HandleAndZoneScope, ...@@ -399,10 +389,9 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
: GraphAndBuilders(main_zone()), : GraphAndBuilders(main_zone()),
jsgraph(this->isolate(), this->graph(), this->common(), nullptr, jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
nullptr, this->machine()), nullptr, this->machine()),
sig(sig),
descriptor_(nullptr), descriptor_(nullptr),
testing_module_(module) { testing_module_(module) {
init_env(&env, sig);
env.module = module;
if (module) { if (module) {
// Get a new function from the testing module. // Get a new function from the testing module.
function_ = nullptr; function_ = nullptr;
...@@ -420,12 +409,13 @@ class WasmFunctionCompiler : public HandleAndZoneScope, ...@@ -420,12 +409,13 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
} }
JSGraph jsgraph; JSGraph jsgraph;
FunctionEnv env; FunctionSig* sig;
// The call descriptor is initialized when the function is compiled. // The call descriptor is initialized when the function is compiled.
CallDescriptor* descriptor_; CallDescriptor* descriptor_;
TestingModule* testing_module_; TestingModule* testing_module_;
WasmFunction* function_; WasmFunction* function_;
int function_index_; int function_index_;
LocalDeclEncoder local_decls;
Isolate* isolate() { return main_isolate(); } Isolate* isolate() { return main_isolate(); }
Graph* graph() const { return main_graph_; } Graph* graph() const { return main_graph_; }
...@@ -434,28 +424,23 @@ class WasmFunctionCompiler : public HandleAndZoneScope, ...@@ -434,28 +424,23 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
MachineOperatorBuilder* machine() { return &main_machine_; } MachineOperatorBuilder* machine() { return &main_machine_; }
void InitializeDescriptor() { void InitializeDescriptor() {
if (descriptor_ == nullptr) { if (descriptor_ == nullptr) {
descriptor_ = env.module->GetWasmCallDescriptor(main_zone(), env.sig); descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig);
} }
} }
CallDescriptor* descriptor() { return descriptor_; } CallDescriptor* descriptor() { return descriptor_; }
void Build(const byte* start, const byte* end) { void Build(const byte* start, const byte* end) {
// Transfer local counts before compiling.
function()->local_i32_count = env.local_i32_count;
function()->local_i64_count = env.local_i64_count;
function()->local_f32_count = env.local_f32_count;
function()->local_f64_count = env.local_f64_count;
// Build the TurboFan graph. // Build the TurboFan graph.
TestBuildingGraph(main_zone(), &jsgraph, &env, start, end); local_decls.Prepend(&start, &end);
TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, start, end);
delete[] start;
} }
byte AllocateLocal(LocalType type) { byte AllocateLocal(LocalType type) {
int result = static_cast<int>(env.total_locals); uint32_t index = local_decls.AddLocals(1, type, sig);
env.AddLocals(type, 1); byte result = static_cast<byte>(index);
byte b = static_cast<byte>(result); DCHECK_EQ(index, result);
CHECK_EQ(result, b); return result;
return b;
} }
// TODO(titzer): remove me. // TODO(titzer): remove me.
...@@ -542,8 +527,6 @@ class WasmRunner { ...@@ -542,8 +527,6 @@ class WasmRunner {
wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3); wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
} }
FunctionEnv* env() { return &compiler_.env; }
// Builds a graph from the given Wasm code and generates the machine // Builds a graph from the given Wasm code and generates the machine
// code and call wrapper for that graph. This method must not be called // code and call wrapper for that graph. This method must not be called
// more than once. // more than once.
...@@ -593,13 +576,7 @@ class WasmRunner { ...@@ -593,13 +576,7 @@ class WasmRunner {
return return_value; return return_value;
} }
byte AllocateLocal(LocalType type) { byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
int result = static_cast<int>(env()->total_locals);
env()->AddLocals(type, 1);
byte b = static_cast<byte>(result);
CHECK_EQ(result, b);
return b;
}
protected: protected:
Zone zone; Zone zone;
......
...@@ -47,6 +47,29 @@ var debug = false; ...@@ -47,6 +47,29 @@ var debug = false;
assertEquals(27777, instance.exports.main(27777)); assertEquals(27777, instance.exports.main(27777));
})(); })();
(function LocalsTest2() {
// TODO(titzer): i64 only works on 64-bit platforms.
var types = [
{locals: {i32_count: 1}, type: kAstI32},
// {locals: {i64_count: 1}, type: kAstI64},
{locals: {f32_count: 1}, type: kAstF32},
{locals: {f64_count: 1}, type: kAstF64},
];
for (p of types) {
var module = new WasmModuleBuilder();
module.addFunction(undefined, [p.type, p.type])
.addLocals(p.locals)
.addBody([kExprSetLocal, 1, kExprGetLocal, 0])
.exportAs("main");
var buffer = module.toBuffer(debug);
var instance = _WASMEXP_.instantiateModule(buffer);
assertEquals(19, instance.exports.main(19));
assertEquals(27777, instance.exports.main(27777));
}
})();
(function CallTest() { (function CallTest() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addFunction("add", [kAstI32, kAstI32, kAstI32]) module.addFunction("add", [kAstI32, kAstI32, kAstI32])
......
...@@ -9,10 +9,7 @@ load("test/mjsunit/wasm/wasm-constants.js"); ...@@ -9,10 +9,7 @@ load("test/mjsunit/wasm/wasm-constants.js");
try { try {
var data = bytes( var data = bytes(
0, kAstStmt, // signature 0, kAstStmt, // signature
3, 0, // local int32 count kDeclNoLocals, // --
4, 0, // local int64 count
5, 0, // local float32 count
6, 0, // local float64 count
kExprNop // body kExprNop // body
); );
...@@ -27,10 +24,7 @@ var threw = false; ...@@ -27,10 +24,7 @@ var threw = false;
try { try {
var data = bytes( var data = bytes(
0, kAstI32, // signature 0, kAstI32, // signature
2, 0, // local int32 count kDeclNoLocals, // --
3, 0, // local int64 count
4, 0, // local float32 count
5, 0, // local float64 count
kExprBlock, 2, kExprNop, kExprNop // body kExprBlock, 2, kExprNop, kExprNop // body
); );
......
...@@ -48,6 +48,8 @@ function bytesWithHeader() { ...@@ -48,6 +48,8 @@ function bytesWithHeader() {
return buffer; return buffer;
} }
var kDeclNoLocals = 0;
// Section declaration constants // Section declaration constants
var kDeclMemory = 0x00; var kDeclMemory = 0x00;
var kDeclSignatures = 0x01; var kDeclSignatures = 0x01;
......
...@@ -190,25 +190,46 @@ WasmModuleBuilder.prototype.toArray = function(debug) { ...@@ -190,25 +190,46 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
var hasName = func.name != undefined && func.name.length > 0; var hasName = func.name != undefined && func.name.length > 0;
names = names || hasName; names = names || hasName;
if (hasName) flags |= kDeclFunctionName; if (hasName) flags |= kDeclFunctionName;
if (func.locals != undefined) flags |= kDeclFunctionLocals;
exports += func.exports.length; exports += func.exports.length;
emit_u8(bytes, flags); emit_u8(bytes, flags);
emit_u16(bytes, func.sig_index); emit_u16(bytes, func.sig_index);
if (hasName) { if (hasName) emit_string(bytes, func.name);
emit_string(bytes, func.name);
// Function body length will be patched later.
var length_pos = bytes.length;
emit_u16(bytes, 0);
var local_decls = [];
var l = func.locals;
if (l != undefined) {
var local_decls_count = 0;
if (l.i32_count > 0) {
local_decls.push({count: l.i32_count, type: kAstI32});
}
if (l.i64_count > 0) {
local_decls.push({count: l.i64_count, type: kAstI64});
}
if (l.f32_count > 0) {
local_decls.push({count: l.f32_count, type: kAstF32});
}
if (l.f64_count > 0) {
local_decls.push({count: l.f64_count, type: kAstF64});
}
} }
if (func.locals != undefined) { emit_u8(bytes, local_decls.length);
emit_u16(bytes, func.locals.i32_count); for (decl of local_decls) {
emit_u16(bytes, func.locals.i64_count); emit_varint(bytes, decl.count);
emit_u16(bytes, func.locals.f32_count); emit_u8(bytes, decl.type);
emit_u16(bytes, func.locals.f64_count);
} }
emit_u16(bytes, func.body.length);
for (var i = 0; i < func.body.length; i++) { for (var i = 0; i < func.body.length; i++) {
emit_u8(bytes, func.body[i]); emit_u8(bytes, func.body[i]);
} }
var length = bytes.length - length_pos - 2;
bytes[length_pos] = length & 0xff;
bytes[length_pos + 1] = (length >> 8) & 0xff;
index++; index++;
} }
......
This diff is collapsed.
...@@ -86,9 +86,6 @@ TEST_F(EncoderTest, Function_Builder_Variable_Indexing) { ...@@ -86,9 +86,6 @@ TEST_F(EncoderTest, Function_Builder_Variable_Indexing) {
byte* header = buffer; byte* header = buffer;
byte* body = buffer + f->HeaderSize(); byte* body = buffer + f->HeaderSize();
f->Serialize(buffer, &header, &body); f->Serialize(buffer, &header, &body);
for (size_t i = 0; i < 7; i++) {
CHECK_EQ(i, static_cast<size_t>(*(buffer + 2 * i + f->HeaderSize() + 1)));
}
} }
...@@ -109,15 +106,6 @@ TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) { ...@@ -109,15 +106,6 @@ TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) {
byte* body = buffer + f->HeaderSize(); byte* body = buffer + f->HeaderSize();
f->Serialize(buffer, &header, &body); f->Serialize(buffer, &header, &body);
body = buffer + f->HeaderSize(); body = buffer + f->HeaderSize();
for (size_t i = 0; i < 127; i++) {
CHECK_EQ(kExprGetLocal, static_cast<size_t>(*(body + 2 * i)));
CHECK_EQ(i + 1, static_cast<size_t>(*(body + 2 * i + 1)));
}
CHECK_EQ(kExprGetLocal, static_cast<size_t>(*(body + 2 * 127)));
CHECK_EQ(0x80, static_cast<size_t>(*(body + 2 * 127 + 1)));
CHECK_EQ(0x01, static_cast<size_t>(*(body + 2 * 127 + 2)));
CHECK_EQ(kExprGetLocal, static_cast<size_t>(*(body + 2 * 127 + 3)));
CHECK_EQ(0x00, static_cast<size_t>(*(body + 2 * 127 + 4)));
} }
......
...@@ -23,25 +23,12 @@ namespace wasm { ...@@ -23,25 +23,12 @@ namespace wasm {
class WasmLoopAssignmentAnalyzerTest : public TestWithZone { class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
public: public:
WasmLoopAssignmentAnalyzerTest() : TestWithZone(), sigs() { WasmLoopAssignmentAnalyzerTest() : num_locals(0) {}
init_env(&env, sigs.v_v());
}
TestSignatures sigs; TestSignatures sigs;
FunctionEnv env; uint32_t num_locals;
static void init_env(FunctionEnv* env, FunctionSig* sig) {
env->module = nullptr;
env->sig = sig;
env->local_i32_count = 0;
env->local_i64_count = 0;
env->local_f32_count = 0;
env->local_f64_count = 0;
env->SumLocals();
}
BitVector* Analyze(const byte* start, const byte* end) { BitVector* Analyze(const byte* start, const byte* end) {
return AnalyzeLoopAssignmentForTesting(zone(), &env, start, end); return AnalyzeLoopAssignmentForTesting(zone(), num_locals, start, end);
} }
}; };
...@@ -60,13 +47,13 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) { ...@@ -60,13 +47,13 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
for (int j = 0; j < assigned->length(); j++) { for (int j = 0; j < assigned->length(); j++) {
CHECK_EQ(false, assigned->Contains(j)); CHECK_EQ(false, assigned->Contains(j));
} }
env.AddLocals(kAstI32, 1); num_locals++;
} }
} }
TEST_F(WasmLoopAssignmentAnalyzerTest, One) { TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
env.AddLocals(kAstI32, 5); num_locals = 5;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i))}; byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i))};
BitVector* assigned = Analyze(code, code + arraysize(code)); BitVector* assigned = Analyze(code, code + arraysize(code));
...@@ -78,7 +65,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, One) { ...@@ -78,7 +65,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) { TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
env.AddLocals(kAstI32, 5); num_locals = 5;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i)), WASM_SET_ZERO(1)}; byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
BitVector* assigned = Analyze(code, code + arraysize(code)); BitVector* assigned = Analyze(code, code + arraysize(code));
...@@ -90,7 +77,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) { ...@@ -90,7 +77,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
TEST_F(WasmLoopAssignmentAnalyzerTest, Two) { TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
env.AddLocals(kAstI32, 5); num_locals = 5;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) { for (int j = 0; j < 5; j++) {
byte code[] = {WASM_LOOP(2, WASM_SET_ZERO(i), WASM_SET_ZERO(j))}; byte code[] = {WASM_LOOP(2, WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
...@@ -105,7 +92,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Two) { ...@@ -105,7 +92,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) { TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
env.AddLocals(kAstI32, 5); num_locals = 5;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP( byte code[] = {WASM_LOOP(
1, WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))}; 1, WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
...@@ -126,7 +113,7 @@ static byte LEBByte(uint32_t val, byte which) { ...@@ -126,7 +113,7 @@ static byte LEBByte(uint32_t val, byte which) {
TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) { TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
env.AddLocals(kAstI32, 65000); num_locals = 65000;
for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) { for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
byte code[] = {kExprLoop, byte code[] = {kExprLoop,
1, 1,
...@@ -148,7 +135,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) { ...@@ -148,7 +135,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
TEST_F(WasmLoopAssignmentAnalyzerTest, Break) { TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
env.AddLocals(kAstI32, 3); num_locals = 3;
byte code[] = { byte code[] = {
WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_SET_ZERO(1)))), WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
WASM_SET_ZERO(0)}; WASM_SET_ZERO(0)};
...@@ -162,7 +149,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Break) { ...@@ -162,7 +149,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) { TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
env.AddLocals(kAstI32, 5); num_locals = 5;
byte code[] = { byte code[] = {
WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0),
WASM_BRV(0, WASM_SET_LOCAL( WASM_BRV(0, WASM_SET_LOCAL(
...@@ -179,9 +166,8 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) { ...@@ -179,9 +166,8 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) { TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
env.AddLocals(kAstI32, 3); num_locals = 6;
const byte kIter = 0; const byte kIter = 0;
env.AddLocals(kAstF32, 3);
const byte kSum = 3; const byte kSum = 3;
byte code[] = {WASM_BLOCK( byte code[] = {WASM_BLOCK(
......
...@@ -903,10 +903,11 @@ class WasmFunctionVerifyTest : public TestWithZone {}; ...@@ -903,10 +903,11 @@ class WasmFunctionVerifyTest : public TestWithZone {};
TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
static const byte data[] = { static const byte data[] = {
0, kLocalVoid, // signature 0, kLocalVoid, // signature
3, 0, // local int32 count 4, // locals
4, 0, // local int64 count 3, kLocalI32, // --
5, 0, // local float32 count 4, kLocalI64, // --
6, 0, // local float64 count 5, kLocalF32, // --
6, kLocalF64, // --
kExprNop // body kExprNop // body
}; };
...@@ -919,12 +920,9 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { ...@@ -919,12 +920,9 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
EXPECT_EQ(0, function->sig->parameter_count()); EXPECT_EQ(0, function->sig->parameter_count());
EXPECT_EQ(0, function->sig->return_count()); EXPECT_EQ(0, function->sig->return_count());
EXPECT_EQ(0, function->name_offset); EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(arraysize(data) - 1, function->code_start_offset); EXPECT_EQ(2, function->code_start_offset);
EXPECT_EQ(arraysize(data), function->code_end_offset); EXPECT_EQ(arraysize(data), function->code_end_offset);
EXPECT_EQ(3, function->local_i32_count); // TODO(titzer): verify encoding of local declarations
EXPECT_EQ(4, function->local_i64_count);
EXPECT_EQ(5, function->local_f32_count);
EXPECT_EQ(6, function->local_f64_count);
EXPECT_FALSE(function->external); EXPECT_FALSE(function->external);
EXPECT_FALSE(function->exported); EXPECT_FALSE(function->exported);
} }
......
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