Commit ebe43399 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Surface V128 in inspector

For now, V128 values are converted to String16 (since they are not
serializable). It is shown as a list of 16 uint8_t (hex). This
description can be tweaked as necessary.

Some updates to ARM64 required to push/pop the full Q register.

Bug: v8:10347
Bug: chromium:1130474
Change-Id: I1bffbb49f47c06da3cd26d830addae0416a4441a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2422082Reviewed-by: 's avatarKim-Anh Tran <kimanh@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70096}
parent f20230af
......@@ -3464,7 +3464,7 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
// Save all parameter registers. They might hold live values, we restore
// them after the runtime call.
__ PushXRegList(WasmDebugBreakFrameConstants::kPushedGpRegs);
__ PushDRegList(WasmDebugBreakFrameConstants::kPushedFpRegs);
__ PushQRegList(WasmDebugBreakFrameConstants::kPushedFpRegs);
// Initialize the JavaScript context with 0. CEntry will use it to
// set the current context on the isolate.
......@@ -3472,7 +3472,7 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
// Restore registers.
__ PopDRegList(WasmDebugBreakFrameConstants::kPushedFpRegs);
__ PopQRegList(WasmDebugBreakFrameConstants::kPushedFpRegs);
__ PopXRegList(WasmDebugBreakFrameConstants::kPushedGpRegs);
}
__ Ret();
......
......@@ -1714,6 +1714,12 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
inline void PopWRegList(RegList regs) {
PopSizeRegList(regs, kWRegSizeInBits);
}
inline void PushQRegList(RegList regs) {
PushSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
}
inline void PopQRegList(RegList regs) {
PopSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
}
inline void PushDRegList(RegList regs) {
PushSizeRegList(regs, kDRegSizeInBits, CPURegister::kVRegister);
}
......
......@@ -110,7 +110,7 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
-RoundUp<16>(TypedFrameConstants::kFixedFrameSizeFromFp) -
kSystemPointerSize * kNumPushedGpRegisters;
static constexpr int kLastPushedFpRegisterOffset =
kLastPushedGpRegisterOffset - kDoubleSize * kNumPushedFpRegisters;
kLastPushedGpRegisterOffset - kSimd128Size * kNumPushedFpRegisters;
// Offsets are fp-relative.
static int GetPushedGpRegisterOffset(int reg_code) {
......@@ -124,7 +124,7 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
DCHECK_NE(0, kPushedFpRegs & (1 << reg_code));
uint32_t lower_regs = kPushedFpRegs & ((uint32_t{1} << reg_code) - 1);
return kLastPushedFpRegisterOffset +
base::bits::CountPopulation(lower_regs) * kDoubleSize;
base::bits::CountPopulation(lower_regs) * kSimd128Size;
}
};
......
......@@ -196,6 +196,14 @@ void String16Builder::appendUnsignedAsHex(uint32_t number) {
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
void String16Builder::appendUnsignedAsHex(uint8_t number) {
constexpr int kBufferSize = 3;
char buffer[kBufferSize];
int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%02" PRIx8, number);
DCHECK_LE(0, chars);
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
String16 String16Builder::toString() {
return String16(m_buffer.data(), m_buffer.size());
}
......
......@@ -128,6 +128,7 @@ class String16Builder {
void appendNumber(size_t);
void appendUnsignedAsHex(uint64_t);
void appendUnsignedAsHex(uint32_t);
void appendUnsignedAsHex(uint8_t);
String16 toString();
void reserveCapacity(size_t);
......
......@@ -54,6 +54,15 @@ ResultType unpackWasmValue(v8::Local<v8::Context> context,
return result;
}
String16 descriptionForWasmS128(std::array<uint8_t, 16> arr) {
String16Builder builder;
for (int i = 0; i < 16; i++) {
builder.appendUnsignedAsHex(arr.at(i));
builder.append(" ");
}
return builder.toString();
}
// Partial list of Wasm's ValueType, copied here to avoid including internal
// header. Using an unscoped enumeration here to allow implicit conversions from
// int. Keep in sync with ValueType::Kind in wasm/value-type.h.
......@@ -176,6 +185,14 @@ Response toProtocolValue(v8::Local<v8::Context> context,
unpackWasmValue<double>(context, wasmValue->bytes()));
break;
}
case kS128: {
auto bytes = wasmValue->bytes();
DCHECK_EQ(16, bytes->Length());
auto s128 = unpackWasmValue<std::array<uint8_t, 16>>(context, bytes);
String16 desc = descriptionForWasmS128(s128);
*result = protocol::StringValue::create(desc);
break;
}
case kExternRef: {
std::unique_ptr<protocol::Value> externrefValue;
Response response = toProtocolValue(context, wasmValue->ref(), maxDepth,
......@@ -525,6 +542,8 @@ class WasmValueMirror final : public ValueMirror {
return RemoteObject::SubtypeEnum::F32;
case kF64:
return RemoteObject::SubtypeEnum::F64;
case kS128:
return RemoteObject::SubtypeEnum::V128;
case kExternRef:
return RemoteObject::SubtypeEnum::Externref;
default:
......@@ -553,6 +572,13 @@ class WasmValueMirror final : public ValueMirror {
return String16::fromDouble(
unpackWasmValue<double>(context, m_value->bytes()));
}
case kS128: {
*serializable = false;
auto bytes = m_value->bytes();
DCHECK_EQ(16, bytes->Length());
auto s128 = unpackWasmValue<std::array<uint8_t, 16>>(context, bytes);
return descriptionForWasmS128(s128);
}
case kExternRef: {
return descriptionForObject(context->GetIsolate(),
m_value->ref().As<v8::Object>());
......
......@@ -19,6 +19,7 @@
#include "src/wasm/baseline/liftoff-compiler.h"
#include "src/wasm/baseline/liftoff-register.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
......@@ -131,6 +132,12 @@ Handle<Object> WasmValueToValueObject(Isolate* isolate, WasmValue value) {
memcpy(bytes->GetDataStartAddress(), &val, sizeof(val));
break;
}
case ValueType::kS128: {
Simd128 s128 = value.to_s128();
bytes = isolate->factory()->NewByteArray(kSimd128Size);
memcpy(bytes->GetDataStartAddress(), s128.bytes(), kSimd128Size);
break;
}
case ValueType::kOptRef: {
if (value.type().is_reference_to(HeapType::kExtern)) {
return isolate->factory()->NewWasmValue(
......@@ -758,16 +765,26 @@ class DebugInfoImpl {
? WasmValue(ReadUnalignedValue<uint32_t>(gp_addr(reg.gp())))
: WasmValue(ReadUnalignedValue<uint64_t>(gp_addr(reg.gp())));
}
// TODO(clemensb/zhin): Fix this for SIMD.
DCHECK(reg.is_fp() || reg.is_fp_pair());
if (reg.is_fp_pair()) UNIMPLEMENTED();
// ifdef here to workaround unreachable code for is_fp_pair.
#ifdef V8_TARGET_ARCH_ARM
int code = reg.is_fp_pair() ? reg.low_fp().code() : reg.fp().code();
#else
int code = reg.fp().code();
#endif
Address spilled_addr =
debug_break_fp +
WasmDebugBreakFrameConstants::GetPushedFpRegisterOffset(
reg.fp().code());
return type == kWasmF32
? WasmValue(ReadUnalignedValue<float>(spilled_addr))
: WasmValue(ReadUnalignedValue<double>(spilled_addr));
WasmDebugBreakFrameConstants::GetPushedFpRegisterOffset(code);
if (type == kWasmF32) {
return WasmValue(ReadUnalignedValue<float>(spilled_addr));
} else if (type == kWasmF64) {
return WasmValue(ReadUnalignedValue<double>(spilled_addr));
} else if (type == kWasmS128) {
return WasmValue(Simd128(ReadUnalignedValue<int16>(spilled_addr)));
} else {
// All other cases should have been handled above.
UNREACHABLE();
}
}
// Otherwise load the value from the stack.
......@@ -782,6 +799,9 @@ class DebugInfoImpl {
return WasmValue(ReadUnalignedValue<float>(stack_address));
case ValueType::kF64:
return WasmValue(ReadUnalignedValue<double>(stack_address));
case ValueType::kS128: {
return WasmValue(Simd128(ReadUnalignedValue<int16>(stack_address)));
}
default:
UNIMPLEMENTED();
}
......
......@@ -44,6 +44,8 @@ class Simd128 {
FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS)
#undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS
const uint8_t* bytes() { return val_; }
private:
uint8_t val_[16] = {0};
};
......
......@@ -4,14 +4,14 @@ Waiting for wasm script to be parsed.
Got wasm script!
Setting breakpoint on line 2 (first instruction) of third function
{
columnNumber : 159
columnNumber : 167
lineNumber : 0
scriptId : <scriptId>
}
Paused:
Script wasm://wasm/7f06385e byte offset 159: Wasm opcode 0x20
Script wasm://wasm/ed01bcee byte offset 167: Wasm opcode 0x20
Scope:
at C (interpreted) (0:159):
at C (interpreted) (0:167):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -22,7 +22,7 @@ at C (interpreted) (0:159):
i32_arg: 42 (i32)
i32_local: 0 (i32)
- scope (wasm-expression-stack):
at B (liftoff) (0:150):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -35,6 +35,7 @@ at B (liftoff) (0:150):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -53,9 +54,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 161: Wasm opcode 0x24
Script wasm://wasm/ed01bcee byte offset 169: Wasm opcode 0x24
Scope:
at C (interpreted) (0:161):
at C (interpreted) (0:169):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -67,7 +68,7 @@ at C (interpreted) (0:161):
i32_local: 0 (i32)
- scope (wasm-expression-stack):
0: 42 (i32)
at B (liftoff) (0:150):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -80,6 +81,7 @@ at B (liftoff) (0:150):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -98,9 +100,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 163: Wasm opcode 0x41
Script wasm://wasm/ed01bcee byte offset 171: Wasm opcode 0x41
Scope:
at C (interpreted) (0:163):
at C (interpreted) (0:171):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -111,7 +113,7 @@ at C (interpreted) (0:163):
i32_arg: 42 (i32)
i32_local: 0 (i32)
- scope (wasm-expression-stack):
at B (liftoff) (0:150):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -124,6 +126,7 @@ at B (liftoff) (0:150):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -142,9 +145,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 165: Wasm opcode 0x21
Script wasm://wasm/ed01bcee byte offset 173: Wasm opcode 0x21
Scope:
at C (interpreted) (0:165):
at C (interpreted) (0:173):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -156,7 +159,7 @@ at C (interpreted) (0:165):
i32_local: 0 (i32)
- scope (wasm-expression-stack):
0: 47 (i32)
at B (liftoff) (0:150):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -169,6 +172,7 @@ at B (liftoff) (0:150):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -187,9 +191,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 167: Wasm opcode 0x0b
Script wasm://wasm/ed01bcee byte offset 175: Wasm opcode 0x0b
Scope:
at C (interpreted) (0:167):
at C (interpreted) (0:175):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -200,7 +204,7 @@ at C (interpreted) (0:167):
i32_arg: 42 (i32)
i32_local: 47 (i32)
- scope (wasm-expression-stack):
at B (liftoff) (0:150):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -213,6 +217,7 @@ at B (liftoff) (0:150):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -231,9 +236,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 152: Wasm opcode 0x1a
Script wasm://wasm/ed01bcee byte offset 160: Wasm opcode 0x1a
Scope:
at B (liftoff) (0:152):
at B (liftoff) (0:160):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -246,6 +251,7 @@ at B (liftoff) (0:152):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
1: 3 (i32)
......@@ -264,9 +270,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 153: Wasm opcode 0x1a
Script wasm://wasm/ed01bcee byte offset 161: Wasm opcode 0x1a
Scope:
at B (liftoff) (0:153):
at B (liftoff) (0:161):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -279,6 +285,7 @@ at B (liftoff) (0:153):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
0: 42 (i32)
at A (liftoff) (0:128):
......@@ -296,9 +303,9 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 154: Wasm opcode 0x0b
Script wasm://wasm/ed01bcee byte offset 162: Wasm opcode 0x0b
Scope:
at B (liftoff) (0:154):
at B (liftoff) (0:162):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
......@@ -311,6 +318,7 @@ at B (liftoff) (0:154):
i32_local: 0 (i32)
f32_local: 7.199999809265137 (f32)
var5: 0 (f32)
v128_local: 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 (v128)
- scope (wasm-expression-stack):
at A (liftoff) (0:128):
- scope (module):
......@@ -327,7 +335,7 @@ at (anonymous) (0:17):
-- skipped globals
Paused:
Script wasm://wasm/7f06385e byte offset 130: Wasm opcode 0x0b
Script wasm://wasm/ed01bcee byte offset 130: Wasm opcode 0x0b
Scope:
at A (liftoff) (0:130):
- scope (module):
......
......@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-type-reflection
// Flags: --experimental-wasm-type-reflection --experimental-wasm-simd
// SIMD in Liftoff only works with these cpu features, force them on.
// Flags: --enable-sse3 --enable-ssse3 --enable-sse4-1
utils.load('test/inspector/wasm-inspector-test.js');
......@@ -83,9 +85,14 @@ async function instantiateWasm() {
builder.addFunction('B (liftoff)', kSig_v_i, ['i32_arg'])
.addLocals(kWasmI32, 1, ['i32_local'])
.addLocals(kWasmF32, 4, ['f32_local', '0', '0'])
.addLocals(kWasmS128, 1, ['v128_local'])
.addBody([
// Load a parameter and a constant onto the operand stack.
kExprLocalGet, 0, kExprI32Const, 3,
// Set local 6 to v128 i32.x4 23, 23, 23, 23.
kExprI32Const, 23,
kSimdPrefix, kExprI32x4Splat,
kExprLocalSet, 6,
// Set local 2 to 7.2.
...wasmF32Const(7.2), kExprLocalSet, 2,
// Call function 'C', forwarding param 0.
......
......@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-type-reflection
// Flags: --experimental-wasm-type-reflection --experimental-wasm-simd
// SIMD in Liftoff only works with these cpu features, force them on.
// Flags: --enable-sse3 --enable-ssse3 --enable-sse4-1
utils.load('test/inspector/wasm-inspector-test.js');
......@@ -87,6 +89,7 @@ async function instantiateWasm() {
.addLocals(kWasmI32, 1)
.addLocals(kWasmI64, 1, ['i64_local'])
.addLocals(kWasmF64, 3, ['unicode☼f64', '0', '0'])
.addLocals(kWasmS128, 1)
.addBody([
// Set param 0 to 11.
kExprI32Const, 11, kExprLocalSet, 0,
......@@ -101,6 +104,10 @@ async function instantiateWasm() {
// Set local 3 to 1/7.
kExprI32Const, 1, kExprF64UConvertI32, kExprI32Const, 7,
kExprF64UConvertI32, kExprF64Div, kExprLocalSet, 3,
// Set local 6 to [23, 23, 23, 23]
kExprI32Const, 23,
kSimdPrefix, kExprI32x4Splat,
kExprLocalSet, 6,
// Set global 0 to 15
kExprI32Const, 15, kExprGlobalSet, 0,
......
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