Bug 1929342 - Inline wasm:js-string length. r=rhunt

Differential Revision: https://phabricator.services.mozilla.com/D228071
This commit is contained in:
Tom Schuster 2024-11-13 17:13:19 +00:00
parent b98dc1b8e2
commit 0cf5041bfe
9 changed files with 73 additions and 2 deletions

View File

@ -22018,6 +22018,19 @@ void CodeGenerator::visitWasmTrapIfAnyRefIsNotJSString(
masm.bind(&isJSString); masm.bind(&isJSString);
} }
void CodeGenerator::visitWasmAnyRefJSStringLength(
LWasmAnyRefJSStringLength* lir) {
Register input = ToRegister(lir->input());
Register output = ToRegister(lir->output());
Register temp = ToRegister(lir->temp0());
Label isJSString;
masm.branchWasmAnyRefIsJSString(true, input, temp, &isJSString);
masm.wasmTrap(lir->mir()->trap(), lir->mir()->bytecodeOffset());
masm.bind(&isJSString);
masm.untagWasmAnyRef(input, temp, wasm::AnyRefTag::String);
masm.loadStringLength(temp, output);
}
void CodeGenerator::visitWasmNewI31Ref(LWasmNewI31Ref* lir) { void CodeGenerator::visitWasmNewI31Ref(LWasmNewI31Ref* lir) {
if (lir->value()->isConstant()) { if (lir->value()->isConstant()) {
// i31ref are often created with constants. If that's the case we will // i31ref are often created with constants. If that's the case we will

View File

@ -4294,6 +4294,13 @@
input: WordSized input: WordSized
num_temps: 1 num_temps: 1
- name: WasmAnyRefJSStringLength
mir_op: true
result_type: WordSized
operands:
input: WordSized
num_temps: 1
- name: WasmNewI31Ref - name: WasmNewI31Ref
mir_op: true mir_op: true
result_type: WordSized result_type: WordSized

View File

@ -3720,6 +3720,13 @@ void LIRGenerator::visitWasmTrapIfAnyRefIsNotJSString(
add(lir, ins); add(lir, ins);
} }
void LIRGenerator::visitWasmAnyRefJSStringLength(
MWasmAnyRefJSStringLength* ins) {
LWasmAnyRefJSStringLength* lir = new (alloc())
LWasmAnyRefJSStringLength(useRegisterAtStart(ins->input()), temp());
define(lir, ins);
}
void LIRGenerator::visitWasmNewI31Ref(MWasmNewI31Ref* ins) { void LIRGenerator::visitWasmNewI31Ref(MWasmNewI31Ref* ins) {
// If it's a constant, it will be put directly into the register. // If it's a constant, it will be put directly into the register.
LWasmNewI31Ref* lir = LWasmNewI31Ref* lir =

View File

@ -679,6 +679,19 @@
guard: true guard: true
clone: true clone: true
- name: WasmAnyRefJSStringLength
operands:
input: WasmAnyRef
arguments:
trap: wasm::Trap
bytecodeOffset: wasm::BytecodeOffset
type_policy: none
result_type: Int32
congruent_to: if_operands_equal
alias_set: none
guard: true
clone: true
- name: WasmNewI31Ref - name: WasmNewI31Ref
operands: operands:
input: Int32 input: Int32

View File

@ -6973,6 +6973,12 @@ void MacroAssembler::extractWasmAnyRefTag(Register src, Register dest) {
andPtr(Imm32(int32_t(wasm::AnyRef::TagMask)), dest); andPtr(Imm32(int32_t(wasm::AnyRef::TagMask)), dest);
} }
void MacroAssembler::untagWasmAnyRef(Register src, Register dest,
wasm::AnyRefTag tag) {
MOZ_ASSERT(tag != wasm::AnyRefTag::ObjectOrNull, "No untagging needed");
computeEffectiveAddress(Address(src, -int32_t(tag)), dest);
}
void MacroAssembler::branchWasmAnyRefIsNull(bool isNull, Register src, void MacroAssembler::branchWasmAnyRefIsNull(bool isNull, Register src,
Label* label) { Label* label) {
branchTestPtr(isNull ? Assembler::Zero : Assembler::NonZero, src, src, label); branchTestPtr(isNull ? Assembler::Zero : Assembler::NonZero, src, src, label);
@ -7579,8 +7585,7 @@ void MacroAssembler::convertWasmAnyRefToValue(Register instance, Register src,
&isObjectOrNull); &isObjectOrNull);
// If we're not i31, object, or null, we must be a string // If we're not i31, object, or null, we must be a string
rshiftPtr(Imm32(wasm::AnyRef::TagShift), src); untagWasmAnyRef(src, src, wasm::AnyRefTag::String);
lshiftPtr(Imm32(wasm::AnyRef::TagShift), src);
moveValue(TypedOrValueRegister(MIRType::String, AnyRegister(src)), dst); moveValue(TypedOrValueRegister(MIRType::String, AnyRegister(src)), dst);
jump(&done); jump(&done);

View File

@ -49,6 +49,7 @@
#include "vm/FunctionFlags.h" #include "vm/FunctionFlags.h"
#include "vm/Opcodes.h" #include "vm/Opcodes.h"
#include "vm/RealmFuses.h" #include "vm/RealmFuses.h"
#include "wasm/WasmAnyRef.h"
// [SMDOC] MacroAssembler multi-platform overview // [SMDOC] MacroAssembler multi-platform overview
// //
@ -4149,6 +4150,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
// Extract the tag of wasm anyref `src`. // Extract the tag of wasm anyref `src`.
void extractWasmAnyRefTag(Register src, Register dest); void extractWasmAnyRefTag(Register src, Register dest);
// Remove the known tag of wasm anyref `src`.
void untagWasmAnyRef(Register src, Register dest, wasm::AnyRefTag tag);
// Branch if the wasm anyref `src` is or is not the null value. // Branch if the wasm anyref `src` is or is not the null value.
void branchWasmAnyRefIsNull(bool isNull, Register src, Label* label); void branchWasmAnyRefIsNull(bool isNull, Register src, Label* label);
// Branch if the wasm anyref `src` is or is not an I31. // Branch if the wasm anyref `src` is or is not an I31.

View File

@ -338,6 +338,7 @@
name: StringLength name: StringLength
type: Args_Int32_GeneralGeneral type: Args_Int32_GeneralGeneral
entry: Instance::stringLength entry: Instance::stringLength
inline_op: StringLength
export: length export: length
params: params:
- 'externref' - 'externref'

View File

@ -985,6 +985,7 @@ enum class BuiltinInlineOp {
StringCast, StringCast,
StringTest, StringTest,
StringLength,
// Op limit. // Op limit.
Limit Limit

View File

@ -3245,6 +3245,16 @@ class FunctionCompiler {
return ins; return ins;
} }
[[nodiscard]] MDefinition* stringLength(MDefinition* string) {
auto* ins = MWasmAnyRefJSStringLength::New(
alloc(), string, wasm::Trap::BadCast, bytecodeOffset());
if (!ins) {
return nullptr;
}
curBlock_->add(ins);
return ins;
}
[[nodiscard]] bool dispatchInlineBuiltinModuleFunc( [[nodiscard]] bool dispatchInlineBuiltinModuleFunc(
const BuiltinModuleFunc& builtinModuleFunc, const DefVector& params) { const BuiltinModuleFunc& builtinModuleFunc, const DefVector& params) {
BuiltinInlineOp inlineOp = builtinModuleFunc.inlineOp(); BuiltinInlineOp inlineOp = builtinModuleFunc.inlineOp();
@ -3270,6 +3280,16 @@ class FunctionCompiler {
iter().setResult(test); iter().setResult(test);
return true; return true;
} }
case BuiltinInlineOp::StringLength: {
MOZ_ASSERT(params.length() == 1);
MDefinition* string = params[0];
MDefinition* length = stringLength(string);
if (!length) {
return false;
}
iter().setResult(length);
return true;
}
case BuiltinInlineOp::None: case BuiltinInlineOp::None:
case BuiltinInlineOp::Limit: case BuiltinInlineOp::Limit:
break; break;