4646import org .graalvm .polyglot .Context ;
4747import org .graalvm .polyglot .Engine ;
4848import org .openjdk .jmh .annotations .Benchmark ;
49+ import org .openjdk .jmh .annotations .CompilerControl ;
50+ import org .openjdk .jmh .annotations .Param ;
4951import org .openjdk .jmh .annotations .Scope ;
5052import org .openjdk .jmh .annotations .Setup ;
5153import org .openjdk .jmh .annotations .State ;
5254import org .openjdk .jmh .annotations .TearDown ;
5355import org .openjdk .jmh .annotations .Threads ;
5456import org .openjdk .jmh .annotations .Warmup ;
5557
58+ import com .oracle .truffle .api .nodes .UnexpectedResultException ;
5659import com .oracle .truffle .api .object .DynamicObject ;
5760import com .oracle .truffle .api .object .Shape ;
5861
@@ -63,17 +66,30 @@ public class DynamicObjectBenchmark extends TruffleBenchmark {
6366 private static final int PROPERTY_KEYS_PER_ITERATION = 1000 ;
6467 static final MethodHandles .Lookup LOOKUP = MethodHandles .lookup ();
6568
66- static final DynamicObject .GetNode GET_NODE = DynamicObject .GetNode .create ();
67- static final DynamicObject .PutNode PUT_NODE = DynamicObject .PutNode .create ();
6869 static final String [] PROPERTY_KEYS = IntStream .range (0 , PROPERTY_KEYS_PER_ITERATION ).mapToObj (i -> "testKey" + i ).toArray (String []::new );
69- static final String SOME_KEY = PROPERTY_KEYS [10 ];
70+ static final String SOME_KEY = PROPERTY_KEYS [0 ];
71+ static final String SOME_KEY_INT = PROPERTY_KEYS [1 ];
72+ static final String SOME_KEY_LONG = PROPERTY_KEYS [2 ];
73+ static final String SOME_KEY_DOUBLE = PROPERTY_KEYS [3 ];
7074
7175 private static final class MyDynamicObject extends DynamicObject {
7276 private MyDynamicObject (Shape shape ) {
7377 super (shape );
7478 }
7579 }
7680
81+ private static final class MyDynamicObjectWithFields extends DynamicObject {
82+ @ DynamicField private long lf1 ;
83+ @ DynamicField private long lf2 ;
84+ @ DynamicField private long lf3 ;
85+ @ DynamicField private Object of0 ;
86+ @ DynamicField private Object of1 ;
87+
88+ MyDynamicObjectWithFields (Shape shape ) {
89+ super (shape );
90+ }
91+ }
92+
7793 @ State (Scope .Benchmark )
7894 public static class SharedEngineState {
7995 final Engine engine = Engine .newBuilder ().allowExperimentalOptions (true ).option ("engine.Compilation" , "false" ).build ();
@@ -107,7 +123,8 @@ public void setup(SharedEngineState shared) {
107123
108124 object = new MyDynamicObject (shared .rootShape );
109125 for (int i = 0 ; i < PROPERTY_KEYS_PER_ITERATION ; i ++) {
110- DynamicObject .PutNode .getUncached ().put (object , PROPERTY_KEYS [i ], "testValue" );
126+ String key = PROPERTY_KEYS [i ];
127+ DynamicObject .PutNode .getUncached ().put (object , key , "testValue" );
111128 }
112129 }
113130
@@ -144,17 +161,98 @@ public void shapeTransitionMapUncontended(SharedEngineState shared, PerThreadCon
144161 }
145162 }
146163
164+ @ State (Scope .Benchmark )
165+ public static class AccessNodeBenchState {
166+
167+ @ Param ({"false" , "true" }) boolean field ;
168+
169+ Shape rootShape ;
170+ DynamicObject object ;
171+
172+ final DynamicObject .GetNode getNode = DynamicObject .GetNode .create ();
173+ final DynamicObject .PutNode putNode = DynamicObject .PutNode .create ();
174+
175+ @ Setup
176+ public void setup () {
177+ rootShape = Shape .newBuilder ().layout (field ? MyDynamicObjectWithFields .class : MyDynamicObject .class , LOOKUP ).build ();
178+ object = field ? new MyDynamicObjectWithFields (rootShape ) : new MyDynamicObject (rootShape );
179+
180+ for (int i = 0 ; i < 10 ; i ++) {
181+ String key = PROPERTY_KEYS [i ];
182+ if (key .equals (SOME_KEY_INT )) {
183+ DynamicObject .PutNode .getUncached ().put (object , key , i );
184+ } else if (key .equals (SOME_KEY_LONG )) {
185+ DynamicObject .PutNode .getUncached ().put (object , key , (long ) i );
186+ } else if (key .equals (SOME_KEY_DOUBLE )) {
187+ DynamicObject .PutNode .getUncached ().put (object , key , (double ) i );
188+ } else {
189+ DynamicObject .PutNode .getUncached ().put (object , key , "testValue" );
190+ }
191+ }
192+ }
193+ }
194+
195+ @ Benchmark
196+ @ Threads (1 )
197+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
198+ public Object get (AccessNodeBenchState state ) {
199+ DynamicObject object = state .object ;
200+ return state .getNode .getOrDefault (object , SOME_KEY , null );
201+ }
202+
203+ @ Benchmark
204+ @ Threads (1 )
205+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
206+ public int getInt (AccessNodeBenchState state ) throws UnexpectedResultException {
207+ DynamicObject object = state .object ;
208+ return state .getNode .getIntOrDefault (object , SOME_KEY_INT , null );
209+ }
210+
211+ @ Benchmark
212+ @ Threads (1 )
213+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
214+ public long getLong (AccessNodeBenchState state ) throws UnexpectedResultException {
215+ DynamicObject object = state .object ;
216+ return state .getNode .getLongOrDefault (object , SOME_KEY_LONG , null );
217+ }
218+
219+ @ Benchmark
220+ @ Threads (1 )
221+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
222+ public double getDouble (AccessNodeBenchState state ) throws UnexpectedResultException {
223+ DynamicObject object = state .object ;
224+ return state .getNode .getDoubleOrDefault (object , SOME_KEY_DOUBLE , null );
225+ }
226+
227+ @ Benchmark
228+ @ Threads (1 )
229+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
230+ public void put (AccessNodeBenchState state ) {
231+ DynamicObject object = state .object ;
232+ state .putNode .put (object , SOME_KEY , "updated value" );
233+ }
234+
235+ @ Benchmark
236+ @ Threads (1 )
237+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
238+ public void putInt (AccessNodeBenchState state ) {
239+ DynamicObject object = state .object ;
240+ state .putNode .put (object , SOME_KEY_INT , 42 );
241+ }
242+
147243 @ Benchmark
148244 @ Threads (1 )
149- public Object get (SharedEngineState shared , PerThreadContextState perThread ) {
150- DynamicObject object = perThread .object ;
151- return GET_NODE .getOrDefault (object , SOME_KEY , null );
245+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
246+ public void putLong (AccessNodeBenchState state ) {
247+ DynamicObject object = state .object ;
248+ state .putNode .put (object , SOME_KEY_LONG , (long ) 42 );
152249 }
153250
154251 @ Benchmark
155252 @ Threads (1 )
156- public void put (SharedEngineState shared , PerThreadContextState perThread ) {
157- DynamicObject object = perThread .object ;
158- PUT_NODE .put (object , SOME_KEY , "updated value" );
253+ @ CompilerControl (CompilerControl .Mode .DONT_INLINE )
254+ public void putDouble (AccessNodeBenchState state ) {
255+ DynamicObject object = state .object ;
256+ state .putNode .put (object , SOME_KEY_DOUBLE , (double ) 42 );
159257 }
160258}
0 commit comments