mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-14 18:43:27 +01:00
Unsafe.putInt and Unsafe.putLong
This commit is contained in:
parent
3de41deb3e
commit
3c2e431a9c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 - 2022 Volker Berlin (i-net software)
|
||||
* Copyright 2018 - 2023 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -65,10 +65,10 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
void init( WasmOptions options, ClassFileLoader classFileLoader ) {
|
||||
void init( @Nonnull WasmOptions options, @Nonnull ClassFileLoader classFileLoader ) {
|
||||
super.init( options, classFileLoader );
|
||||
this.branchManager = new BranchManager( options, getInstructions(), getLocalVariables() );
|
||||
this.unsafeManager = new UnsafeManager( options.functions );
|
||||
this.unsafeManager = new UnsafeManager( options, classFileLoader );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package de.inetsoftware.jwebassembly.module;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -23,10 +24,12 @@ import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import de.inetsoftware.classparser.FieldInfo;
|
||||
import de.inetsoftware.jwebassembly.WasmException;
|
||||
import de.inetsoftware.jwebassembly.module.StackInspector.StackValue;
|
||||
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
|
||||
import de.inetsoftware.jwebassembly.wasm.ValueType;
|
||||
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
|
||||
|
||||
@ -84,16 +87,27 @@ class UnsafeManager {
|
||||
@Nonnull
|
||||
private final FunctionManager functions;
|
||||
|
||||
@Nonnull
|
||||
private final TypeManager types;
|
||||
|
||||
@Nonnull
|
||||
private final ClassFileLoader classFileLoader;
|
||||
|
||||
private final HashMap<FunctionName, UnsafeState> unsafes = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance of the manager
|
||||
*
|
||||
* @param functions
|
||||
* The function manager to register the synthetic functions.
|
||||
* @param options
|
||||
* compiler option/properties
|
||||
* @param classFileLoader
|
||||
* for loading the class files
|
||||
*/
|
||||
UnsafeManager( @Nonnull FunctionManager functions ) {
|
||||
this.functions = functions;
|
||||
UnsafeManager( @Nonnull WasmOptions options, @Nonnull ClassFileLoader classFileLoader ) {
|
||||
this.functions = options.functions;
|
||||
this.types = options.types;
|
||||
this.classFileLoader = classFileLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,8 +115,10 @@ class UnsafeManager {
|
||||
*
|
||||
* @param instructions
|
||||
* the instruction list of a function/method
|
||||
* @throws IOException
|
||||
* If any I/O error occur
|
||||
*/
|
||||
void replaceUnsafe( List<WasmInstruction> instructions ) {
|
||||
void replaceUnsafe( @Nonnull List<WasmInstruction> instructions ) throws IOException {
|
||||
// search for Unsafe function calls
|
||||
for( int i = 0; i < instructions.size(); i++ ) {
|
||||
WasmInstruction instr = instructions.get( i );
|
||||
@ -135,8 +151,10 @@ class UnsafeManager {
|
||||
* the index in the instructions
|
||||
* @param callInst
|
||||
* the method call to Unsafe
|
||||
* @throws IOException
|
||||
* If any I/O error occur
|
||||
*/
|
||||
private void patch( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst ) {
|
||||
private void patch( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst ) throws IOException {
|
||||
FunctionName name = callInst.getFunctionName();
|
||||
switch( name.signatureName ) {
|
||||
case "sun/misc/Unsafe.getUnsafe()Lsun/misc/Unsafe;":
|
||||
@ -332,8 +350,10 @@ class UnsafeManager {
|
||||
* the index in the instructions
|
||||
* @param callInst
|
||||
* the method call to Unsafe
|
||||
* @throws IOException
|
||||
* If any I/O error occur
|
||||
*/
|
||||
private void patch_objectFieldOffset_Java8( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst ) {
|
||||
private void patch_objectFieldOffset_Java8( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst ) throws IOException {
|
||||
UnsafeState state = findUnsafeState( instructions, idx );
|
||||
|
||||
// objectFieldOffset() has 2 parameters THIS(Unsafe) and a Field
|
||||
@ -359,6 +379,7 @@ class UnsafeManager {
|
||||
throw new WasmException( "Unsupported Unsafe method to get target field: " + fieldFuncName.signatureName, -1 );
|
||||
}
|
||||
|
||||
useFieldName( state );
|
||||
nop( instructions, from, idx + 2 );
|
||||
}
|
||||
|
||||
@ -373,8 +394,10 @@ class UnsafeManager {
|
||||
* the method call to Unsafe
|
||||
* @param isAtomicReferenceFieldUpdater
|
||||
* true, if is AtomicReferenceFieldUpdater
|
||||
* @throws IOException
|
||||
* If any I/O error occur
|
||||
*/
|
||||
private void patch_objectFieldOffset_Java11( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst, boolean isAtomicReferenceFieldUpdater ) {
|
||||
private void patch_objectFieldOffset_Java11( List<WasmInstruction> instructions, int idx, WasmCallInstruction callInst, boolean isAtomicReferenceFieldUpdater ) throws IOException {
|
||||
UnsafeState state = findUnsafeState( instructions, idx );
|
||||
|
||||
// objectFieldOffset() has 3 parameters THIS(Unsafe), class and the fieldname
|
||||
@ -389,6 +412,7 @@ class UnsafeManager {
|
||||
stackValue = StackInspector.findInstructionThatPushValue( paramInstructions, classParamIdx, callInst.getCodePosition() );
|
||||
state.typeName = getClassConst( instructions, stackValue );
|
||||
|
||||
useFieldName( state );
|
||||
nop( instructions, from, idx + 2 );
|
||||
}
|
||||
|
||||
@ -435,6 +459,20 @@ class UnsafeManager {
|
||||
instructions.set( idx, new WasmConstNumberInstruction( 1, callInst.getCodePosition(), callInst.getLineNumber() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the field as used
|
||||
*
|
||||
* @param state
|
||||
* the state
|
||||
* @throws IOException
|
||||
* If any I/O error occur
|
||||
*/
|
||||
private void useFieldName( @Nonnull UnsafeState state ) throws IOException {
|
||||
FieldInfo fieldInfo = classFileLoader.get( state.typeName ).getField( state.fieldName );
|
||||
NamedStorageType fieldName = new NamedStorageType( state.typeName, fieldInfo, types );
|
||||
types.valueOf( state.typeName ).useFieldName( fieldName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch an unsafe function that access a field
|
||||
*
|
||||
@ -550,10 +588,17 @@ class UnsafeManager {
|
||||
+ " local.get 3" // x
|
||||
+ " struct.set " + state.typeName + ' ' + state.fieldName;
|
||||
|
||||
case "getInt":
|
||||
case "getLong":
|
||||
return "local.get 1" // THIS
|
||||
+ " struct.get " + state.typeName + ' ' + state.fieldName //
|
||||
+ " return";
|
||||
|
||||
case "getObjectVolatile":
|
||||
return "local.get 1" // array
|
||||
+ " local.get 2" // the array index
|
||||
+ " array.get " + state.typeName;
|
||||
+ " array.get " + state.typeName
|
||||
+ " return";
|
||||
}
|
||||
|
||||
throw new RuntimeException( name.signatureName );
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 - 2022 Volker Berlin (i-net software)
|
||||
* Copyright 2018 - 2023 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -103,7 +103,7 @@ public abstract class WasmCodeBuilder {
|
||||
* @param classFileLoader
|
||||
* for loading the class files
|
||||
*/
|
||||
void init( WasmOptions options, ClassFileLoader classFileLoader ) {
|
||||
void init( @Nonnull WasmOptions options, @Nonnull ClassFileLoader classFileLoader ) {
|
||||
this.localVariables.init( options.types );
|
||||
this.types = options.types;
|
||||
this.functions = options.functions;
|
||||
@ -250,10 +250,20 @@ public abstract class WasmCodeBuilder {
|
||||
*
|
||||
* @return the type manager
|
||||
*/
|
||||
@Nonnull
|
||||
protected TypeManager getTypeManager() {
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* For loading missing class declarations
|
||||
* @return the loader
|
||||
*/
|
||||
@Nonnull
|
||||
protected ClassFileLoader getClassFileLoader() {
|
||||
return classFileLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the code builder.
|
||||
*
|
||||
|
@ -229,6 +229,7 @@ class WasmStructInstruction extends WasmInstruction {
|
||||
}
|
||||
}
|
||||
comment = fieldName.getName();
|
||||
assert idx >=0;
|
||||
break;
|
||||
case INSTANCEOF:
|
||||
case CAST:
|
||||
|
74
test/de/inetsoftware/jwebassembly/runtime/ThreadTest.java
Normal file
74
test/de/inetsoftware/jwebassembly/runtime/ThreadTest.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2023 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.inetsoftware.jwebassembly.runtime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import de.inetsoftware.jwebassembly.ScriptEngine;
|
||||
import de.inetsoftware.jwebassembly.WasmRule;
|
||||
import de.inetsoftware.jwebassembly.api.annotation.Export;
|
||||
import de.inetsoftware.jwebassembly.web.DOMString;
|
||||
import de.inetsoftware.jwebassembly.web.JSObject;
|
||||
|
||||
/**
|
||||
* @author Volker Berlin
|
||||
*/
|
||||
public class ThreadTest extends AbstractBaseTest {
|
||||
|
||||
@ClassRule
|
||||
public static WasmRule rule = new WasmRule( TestClass.class );
|
||||
|
||||
public ThreadTest( ScriptEngine script, String method, Object[] params ) {
|
||||
super( rule, script, method, params );
|
||||
}
|
||||
|
||||
@Parameters( name = "{0}-{1}" )
|
||||
public static Collection<Object[]> data() {
|
||||
ArrayList<Object[]> list = new ArrayList<>();
|
||||
for( ScriptEngine script : ScriptEngine.testEngines() ) {
|
||||
addParam( list, script, "currentThreadName" );
|
||||
addParam( list, script, "groupThreadName" );
|
||||
}
|
||||
rule.setTestParameters( list );
|
||||
return list;
|
||||
}
|
||||
|
||||
static class TestClass {
|
||||
|
||||
@Export
|
||||
static DOMString currentThreadName() {
|
||||
Thread thread = Thread.currentThread();
|
||||
String name = thread.getName();
|
||||
return JSObject.domString( name );
|
||||
}
|
||||
|
||||
@Export
|
||||
static DOMString groupThreadName() {
|
||||
Thread thread = Thread.currentThread();
|
||||
ThreadGroup group = thread.getThreadGroup();
|
||||
String name;
|
||||
do {
|
||||
name = group.getName();
|
||||
group = group.getParent();
|
||||
} while( group != null );
|
||||
return JSObject.domString( name );
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -58,6 +59,7 @@ public class UnsafeTest extends AbstractBaseTest {
|
||||
addParam( list, script, "getAndSetReference" );
|
||||
addParam( list, script, "lazySetReference" );
|
||||
addParam( list, script, "atomicReferenceFieldUpdater" );
|
||||
addParam( list, script, "putLong" );
|
||||
}
|
||||
rule.setTestParameters( list );
|
||||
|
||||
@ -179,5 +181,11 @@ public class UnsafeTest extends AbstractBaseTest {
|
||||
stream.close();
|
||||
return 42;
|
||||
}
|
||||
|
||||
@Export
|
||||
static int putLong() {
|
||||
ThreadLocalRandom.current().nextInt();
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user