Skip to content

Commit

Permalink
[JSC] Decode local indices at runtime in WASM in-place interpreter
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=270376
rdar://123720682

Reviewed by Justin Michaud and Yusuke Suzuki.

Removes metadata generation for local.get, local.set, and local.tee
from the WASM in-place interpreter. Instead, local indices for these
instructions are decoded at runtime. Since most local indices are
small, this actually saves us time - the added microbenchmark runs
3% faster with this change. More importantly, this saves on memory,
eliminating metadata for the most common WASM instructions.

* JSTests/microbenchmarks/local-get-set-tee.wasm: Added.
* Source/JavaScriptCore/llint/InPlaceInterpreter.asm:
* Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp:
(JSC::Wasm::IPIntGenerator::getLocal):
(JSC::Wasm::IPIntGenerator::setLocal):

Canonical link: https://commits.webkit.org/275815@main
  • Loading branch information
ddegazio committed Mar 8, 2024
1 parent 1cf947c commit bfe0170
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 55 deletions.
Binary file added JSTests/microbenchmarks/local-get-set-tee.wasm
Binary file not shown.
97 changes: 47 additions & 50 deletions Source/JavaScriptCore/llint/InPlaceInterpreter.asm
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,11 @@ macro instructionLabel(instrname)
_ipint%instrname%_validate:
end

macro slowPathLabel(instrname)
alignment()
_ipint%instrname%_slow_path:
end

macro unimplementedInstruction(instrname)
instructionLabel(instrname)
break
Expand Down Expand Up @@ -1284,74 +1289,38 @@ reservedOpcode(0x1f)

instructionLabel(_local_get)
# local.get
loadb [PM, MC], t1
bineq t1, 0, .ipint_local_get_longpath

loadb 1[PB, PC], t0
# Index into locals
loadq [PL, t0, LocalSize], t0
# Push to stack
pushQuad(t0)
advancePC(2)
advanceMC(1)
nextIPIntInstruction()

.ipint_local_get_longpath:
# Load pre-computed index from metadata
loadi 1[PM, MC], t0
bbaeq t0, 128, _ipint_local_get_slow_path
.ipint_local_get_post_decode:
# Index into locals
loadq [PL, t0, LocalSize], t0
# Push to stack
pushQuad(t0)

advancePCByReg(t1)
advanceMC(5)
nextIPIntInstruction()

instructionLabel(_local_set)
# local.set
# Pop from stack
loadb [PM, MC], t1
popQuad(t2, t3)

bineq t1, 0, .ipint_local_set_longpath

loadb 1[PB, PC], t0
# Store to locals
storeq t2, [PL, t0, LocalSize]
advancePC(2)
advanceMC(1)
nextIPIntInstruction()

.ipint_local_set_longpath:
# Load pre-computed index from metadata
loadi 1[PM, MC], t0
bbaeq t0, 128, _ipint_local_set_slow_path
.ipint_local_set_post_decode:
# Pop from stack
popQuad(t2, t3)
# Store to locals
storeq t2, [PL, t0, LocalSize]

advancePCByReg(t1)
advanceMC(5)
nextIPIntInstruction()

instructionLabel(_local_tee)
# local.tee
loadb [PM, MC], t1
loadq [sp], t2
bineq t1, 0, .ipint_local_tee_longpath

loadb 1[PB, PC], t0
storeq t2, [PL, t0, LocalSize]

advancePC(2)
advanceMC(2)
nextIPIntInstruction()

.ipint_local_tee_longpath:
loadi 1[PM, MC], t0
bbaeq t0, 128, _ipint_local_tee_slow_path
.ipint_local_tee_post_decode:
# Load from stack
loadq [sp], t2
# Store to locals
storeq t2, [PL, t0, LocalSize]

advancePCByReg(t1)
advanceMC(10)
nextIPIntInstruction()

instructionLabel(_global_get)
Expand Down Expand Up @@ -5725,9 +5694,37 @@ instructionLabel(_i64_atomic_rmw32_cmpxchg_u)
pushInt64(expected)
end)

##################################
## "Out of line" logic for call ##
##################################
#######################################
## ULEB128 decoding logic for locals ##
#######################################

macro decodeULEB128(exitLabel, result)
# result should already be the first byte.
andq 0x7f, result
move 7, t2 # t1 holds the shift.
.loop:
loadb [PB, PC], t3
andq t3, 0x7f, t1
lshiftq t2, t1
orq t1, result
addq 7, t2
advancePC(1)
bbaeq t3, 128, .loop
jmp exitLabel
end

slowPathLabel(_local_get)
decodeULEB128(.ipint_local_get_post_decode, t0)

slowPathLabel(_local_set)
decodeULEB128(.ipint_local_set_post_decode, t0)

slowPathLabel(_local_tee)
decodeULEB128(.ipint_local_tee_post_decode, t0)

##################################
## "Out of line" logic for call ##
##################################

# FIXME: switch offlineasm unalignedglobal to take alignment and optionally pad with breakpoint instructions (rdar://113594783)
macro mintAlign()
Expand Down
11 changes: 6 additions & 5 deletions Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,17 +723,18 @@ PartialResult WARN_UNUSED_RETURN IPIntGenerator::addLocal(Type, uint32_t count)
return { };
}

PartialResult WARN_UNUSED_RETURN IPIntGenerator::getLocal(uint32_t index, ExpressionType&)
PartialResult WARN_UNUSED_RETURN IPIntGenerator::getLocal(uint32_t, ExpressionType&)
{
// Local indices are usually very small, so we decode them on the fly
// instead of generating metadata.
changeStackSize(1);
m_metadata->addCondensedLocalIndexAndLength(index, getCurrentInstructionLength());
return { };
}

PartialResult WARN_UNUSED_RETURN IPIntGenerator::setLocal(uint32_t index, ExpressionType)
PartialResult WARN_UNUSED_RETURN IPIntGenerator::setLocal(uint32_t, ExpressionType)
{
// Local indices are usually very small, so we decode them on the fly
// instead of generating metadata.
changeStackSize(-1);
m_metadata->addCondensedLocalIndexAndLength(index, getCurrentInstructionLength());
return { };
}

Expand Down

0 comments on commit bfe0170

Please sign in to comment.