32 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName; |
32 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName; |
33 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount; |
33 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount; |
34 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; |
34 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; |
35 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; |
35 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; |
36 |
36 |
37 import java.util.Iterator; |
|
38 import java.util.List; |
37 import java.util.List; |
39 import jdk.nashorn.internal.codegen.types.Type; |
38 import jdk.nashorn.internal.codegen.types.Type; |
40 import jdk.nashorn.internal.ir.Symbol; |
39 import jdk.nashorn.internal.ir.Symbol; |
41 import jdk.nashorn.internal.runtime.Context; |
40 import jdk.nashorn.internal.runtime.Context; |
42 import jdk.nashorn.internal.runtime.JSType; |
41 import jdk.nashorn.internal.runtime.JSType; |
89 this.evalCode = codegen.isEvalCode(); |
88 this.evalCode = codegen.isEvalCode(); |
90 countFields(); |
89 countFields(); |
91 findClass(); |
90 findClass(); |
92 } |
91 } |
93 |
92 |
94 /** |
93 @Override |
95 * Construct an object. |
94 public void createObject(final MethodEmitter method) { |
96 * |
|
97 * @param method the method emitter |
|
98 */ |
|
99 @Override |
|
100 protected void makeObject(final MethodEmitter method) { |
|
101 makeMap(); |
95 makeMap(); |
102 final String className = getClassName(); |
96 final String className = getClassName(); |
103 try { |
97 // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects, |
104 // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects, |
98 // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type |
105 // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type |
99 // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the |
106 // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the |
100 // exact type information is needed for generating continuations in rest-of methods. If we didn't do this, |
107 // exact type information is needed for generating continuations in rest-of methods. If we didn't do this, |
101 // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the |
108 // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the |
102 // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and |
109 // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and |
103 // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification. |
110 // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification. |
104 assert fieldObjectClass != null; |
111 method._new(Context.forStructureClass(className.replace('/', '.'))).dup(); |
105 method._new(fieldObjectClass).dup(); |
112 } catch (final ClassNotFoundException e) { |
106 |
113 throw new AssertionError(e); |
|
114 } |
|
115 loadMap(method); //load the map |
107 loadMap(method); //load the map |
116 |
108 |
117 if (isScope()) { |
109 if (isScope()) { |
118 loadScope(method); |
110 loadScope(method); |
119 |
111 |
124 method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class)); |
116 method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class)); |
125 } |
117 } |
126 } else { |
118 } else { |
127 method.invoke(constructorNoLookup(className, PropertyMap.class)); |
119 method.invoke(constructorNoLookup(className, PropertyMap.class)); |
128 } |
120 } |
129 |
121 } |
130 helpOptimisticRecognizeDuplicateIdentity(method); |
122 |
131 |
123 @Override |
|
124 public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) { |
|
125 method.load(objectType, objectSlot); |
132 // Set values. |
126 // Set values. |
133 final Iterator<MapTuple<T>> iter = tuples.iterator(); |
127 for (int i = start; i < end; i++) { |
134 |
128 final MapTuple<T> tuple = tuples.get(i); |
135 while (iter.hasNext()) { |
|
136 final MapTuple<T> tuple = iter.next(); |
|
137 //we only load when we have both symbols and values (which can be == the symbol) |
129 //we only load when we have both symbols and values (which can be == the symbol) |
138 //if we didn't load, we need an array property |
130 //if we didn't load, we need an array property |
139 if (tuple.symbol != null && tuple.value != null) { |
131 if (tuple.symbol != null && tuple.value != null) { |
140 final int index = getArrayIndex(tuple.key); |
132 final int index = getArrayIndex(tuple.key); |
141 method.dup(); |
133 method.dup(); |
210 } catch (final ClassNotFoundException e) { |
202 } catch (final ClassNotFoundException e) { |
211 throw new AssertionError("Nashorn has encountered an internal error. Structure can not be created."); |
203 throw new AssertionError("Nashorn has encountered an internal error. Structure can not be created."); |
212 } |
204 } |
213 } |
205 } |
214 |
206 |
|
207 @Override |
|
208 protected Class<? extends ScriptObject> getAllocatorClass() { |
|
209 return fieldObjectClass; |
|
210 } |
|
211 |
215 /** |
212 /** |
216 * Get the class name for the object class, |
213 * Get the class name for the object class, |
217 * e.g. {@code com.nashorn.oracle.scripts.JO2P0} |
214 * e.g. {@code com.nashorn.oracle.scripts.JO2P0} |
218 * |
215 * |
219 * @return script class name |
216 * @return script class name |