Commit 494fd715 authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Introduce EmitVarInt and EmitWithVarInt

Use them to encode int32 constants properly.
This reduces the generated wasm size in the unity benchmark from
21.6 MB to 16.8 MB (-22.2%).
This hopefully also translates to increased performance especially on
mobile because of lower memory usage.

R=bradnelson@chromium.org, titzer@chromium.org

Review-Url: https://codereview.chromium.org/2692943002
Cr-Commit-Position: refs/heads/master@{#43200}
parent 2f8ad11f
...@@ -683,35 +683,26 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { ...@@ -683,35 +683,26 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (type->IsA(AsmType::Signed())) { if (type->IsA(AsmType::Signed())) {
int32_t i = 0; int32_t i = 0;
if (!value->ToInt32(&i)) { CHECK(value->ToInt32(&i));
UNREACHABLE(); current_function_builder_->EmitI32Const(i);
}
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) { } else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) {
uint32_t u = 0; uint32_t u = 0;
if (!value->ToUint32(&u)) { CHECK(value->ToUint32(&u));
UNREACHABLE(); current_function_builder_->EmitI32Const(bit_cast<int32_t>(u));
}
int32_t i = static_cast<int32_t>(u);
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (type->IsA(AsmType::Int())) { } else if (type->IsA(AsmType::Int())) {
// The parser can collapse !0, !1 etc to true / false. // The parser can collapse !0, !1 etc to true / false.
// Allow these as int literals. // Allow these as int literals.
if (expr->raw_value()->IsTrue()) { if (expr->raw_value()->IsTrue()) {
byte code[] = {WASM_I32V(1)}; byte code[] = {WASM_ONE};
current_function_builder_->EmitCode(code, sizeof(code)); current_function_builder_->EmitCode(code, sizeof(code));
} else if (expr->raw_value()->IsFalse()) { } else if (expr->raw_value()->IsFalse()) {
byte code[] = {WASM_I32V(0)}; byte code[] = {WASM_ZERO};
current_function_builder_->EmitCode(code, sizeof(code)); current_function_builder_->EmitCode(code, sizeof(code));
} else if (expr->raw_value()->IsNumber()) { } else if (expr->raw_value()->IsNumber()) {
// This can happen when -x becomes x * -1 (due to the parser). // This can happen when -x becomes x * -1 (due to the parser).
int32_t i = 0; int32_t i = 0;
if (!value->ToInt32(&i) || i != -1) { CHECK(value->ToInt32(&i) && i == -1);
UNREACHABLE(); byte code[] = {WASM_I32V_1(-1)};
}
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code)); current_function_builder_->EmitCode(code, sizeof(code));
} else { } else {
UNREACHABLE(); UNREACHABLE();
......
...@@ -62,13 +62,20 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) ...@@ -62,13 +62,20 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
direct_calls_(builder->zone()), direct_calls_(builder->zone()),
asm_offsets_(builder->zone(), 8) {} asm_offsets_(builder->zone(), 8) {}
void WasmFunctionBuilder::EmitVarInt(int32_t val) {
byte buffer[5];
byte* ptr = buffer;
LEBHelper::write_i32v(&ptr, val);
DCHECK_GE(5, ptr - buffer);
body_.insert(body_.end(), buffer, ptr);
}
void WasmFunctionBuilder::EmitVarUint(uint32_t val) { void WasmFunctionBuilder::EmitVarUint(uint32_t val) {
byte buffer[8]; byte buffer[5];
byte* ptr = buffer; byte* ptr = buffer;
LEBHelper::write_u32v(&ptr, val); LEBHelper::write_u32v(&ptr, val);
for (byte* p = buffer; p < ptr; p++) { DCHECK_GE(5, ptr - buffer);
body_.push_back(*p); body_.insert(body_.end(), buffer, ptr);
}
} }
void WasmFunctionBuilder::SetSignature(FunctionSig* sig) { void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
...@@ -116,6 +123,11 @@ void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1, ...@@ -116,6 +123,11 @@ void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
body_.push_back(imm2); body_.push_back(imm2);
} }
void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode, int32_t immediate) {
body_.push_back(static_cast<byte>(opcode));
EmitVarInt(immediate);
}
void WasmFunctionBuilder::EmitWithVarUint(WasmOpcode opcode, void WasmFunctionBuilder::EmitWithVarUint(WasmOpcode opcode,
uint32_t immediate) { uint32_t immediate) {
body_.push_back(static_cast<byte>(opcode)); body_.push_back(static_cast<byte>(opcode));
...@@ -123,13 +135,7 @@ void WasmFunctionBuilder::EmitWithVarUint(WasmOpcode opcode, ...@@ -123,13 +135,7 @@ void WasmFunctionBuilder::EmitWithVarUint(WasmOpcode opcode,
} }
void WasmFunctionBuilder::EmitI32Const(int32_t value) { void WasmFunctionBuilder::EmitI32Const(int32_t value) {
if (-64 <= value && value <= 63) { EmitWithVarInt(kExprI32Const, value);
EmitWithU8(kExprI32Const, static_cast<byte>(value & 0x7F));
} else {
// TODO(titzer): variable-length signed and unsigned i32 constants.
byte code[] = {WASM_I32V_5(value)};
EmitCode(code, sizeof(code));
}
} }
void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) { void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
......
...@@ -121,6 +121,7 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { ...@@ -121,6 +121,7 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
// Building methods. // Building methods.
void SetSignature(FunctionSig* sig); void SetSignature(FunctionSig* sig);
uint32_t AddLocal(ValueType type); uint32_t AddLocal(ValueType type);
void EmitVarInt(int32_t val);
void EmitVarUint(uint32_t val); void EmitVarUint(uint32_t val);
void EmitCode(const byte* code, uint32_t code_size); void EmitCode(const byte* code, uint32_t code_size);
void Emit(WasmOpcode opcode); void Emit(WasmOpcode opcode);
...@@ -130,6 +131,7 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { ...@@ -130,6 +131,7 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
void EmitI32Const(int32_t val); void EmitI32Const(int32_t val);
void EmitWithU8(WasmOpcode opcode, const byte immediate); void EmitWithU8(WasmOpcode opcode, const byte immediate);
void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2); void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
void EmitWithVarInt(WasmOpcode opcode, int32_t immediate);
void EmitWithVarUint(WasmOpcode opcode, uint32_t immediate); void EmitWithVarUint(WasmOpcode opcode, uint32_t immediate);
void EmitDirectCallIndex(uint32_t index); void EmitDirectCallIndex(uint32_t index);
void ExportAs(Vector<const char> name); void ExportAs(Vector<const char> name);
......
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