17
17
import org .truffleruby .builtins .CoreMethod ;
18
18
import org .truffleruby .builtins .CoreMethodArrayArgumentsNode ;
19
19
import org .truffleruby .builtins .CoreModule ;
20
+ import org .truffleruby .builtins .Primitive ;
21
+ import org .truffleruby .builtins .PrimitiveArrayArgumentsNode ;
22
+ import org .truffleruby .builtins .UnaryCoreMethodNode ;
20
23
import org .truffleruby .core .CoreLibrary ;
21
24
import org .truffleruby .core .inlined .AlwaysInlinedMethodNode ;
22
25
import org .truffleruby .core .module .RubyModule ;
23
- import org .truffleruby .language .Nil ;
24
26
import org .truffleruby .language .RubyDynamicObject ;
25
27
import org .truffleruby .language .Visibility ;
26
28
import org .truffleruby .language .arguments .RubyArguments ;
37
39
import com .oracle .truffle .api .profiles .BranchProfile ;
38
40
import com .oracle .truffle .api .source .SourceSection ;
39
41
42
+ import static org .truffleruby .language .RubyBaseNode .nil ;
43
+
40
44
@ CoreModule (value = "Class" , isClass = true )
41
45
public abstract class ClassNodes {
42
46
43
47
/** Special constructor for class Class */
44
48
@ TruffleBoundary
45
- public static RubyClass createClassClass (RubyLanguage language ) {
49
+ public static RubyClass createClassClassAndBootClasses (RubyLanguage language ) {
46
50
final RubyClass rubyClass = new RubyClass (language , language .classShape );
47
51
48
52
assert rubyClass .getLogicalClass () == rubyClass ;
@@ -56,22 +60,7 @@ public static RubyClass createClassClass(RubyLanguage language) {
56
60
@ TruffleBoundary
57
61
public static RubyClass createBootClass (RubyLanguage language , RubyClass classClass , Object superclass ,
58
62
String name ) {
59
- final RubyClass rubyClass = new RubyClass (
60
- classClass ,
61
- language ,
62
- null ,
63
- null ,
64
- name ,
65
- false ,
66
- null ,
67
- superclass );
68
- rubyClass .fields .setFullName (name );
69
-
70
- if (superclass != Nil .INSTANCE ) {
71
- rubyClass .setSuperClass ((RubyClass ) superclass );
72
- }
73
-
74
- return rubyClass ;
63
+ return new RubyClass (classClass , language , null , null , name , false , null , superclass );
75
64
}
76
65
77
66
@ TruffleBoundary
@@ -131,46 +120,15 @@ private static RubyClass createRubyClass(RubyContext context,
131
120
132
121
if (lexicalParent != null ) {
133
122
rubyClass .fields .getAdoptedByLexicalParent (context , lexicalParent , name , null );
134
- } else if (name != null ) { // bootstrap module
135
- rubyClass .fields .setFullName (name );
136
- }
137
-
138
- rubyClass .setSuperClass (superclass );
139
-
140
- return rubyClass ;
141
- }
142
-
143
- @ TruffleBoundary
144
- public static RubyClass createUninitializedRubyClass (RubyContext context ,
145
- SourceSection sourceSection ,
146
- RubyClass classClass ) {
147
- if (classClass != context .getCoreLibrary ().classClass ) {
148
- throw CompilerDirectives .shouldNotReachHere ("Subclasses of class Class are forbidden in Ruby" );
149
123
}
150
124
151
- final RubyClass rubyClass = new RubyClass (
152
- classClass ,
153
- context .getLanguageSlow (),
154
- sourceSection ,
155
- null ,
156
- null ,
157
- false ,
158
- null ,
159
- null );
160
-
161
- // For Class.allocate, set it in the fields but not in RubyClass#superclass to mark as not yet initialized
162
- rubyClass .fields .setSuperClass (context .getCoreLibrary ().objectClass );
163
-
164
- assert !rubyClass .isInitialized ();
165
125
return rubyClass ;
166
126
}
167
127
168
128
@ TruffleBoundary
169
- public static void initialize (RubyContext context , RubyClass rubyClass , RubyClass superclass ) {
129
+ public static void initialize (RubyContext context , RubyClass rubyClass ) {
170
130
assert !rubyClass .isSingleton : "Singleton classes can only be created internally" ;
171
131
172
- rubyClass .setSuperClass (superclass );
173
-
174
132
ensureItHasSingletonClassCreated (context , rubyClass );
175
133
}
176
134
@@ -209,11 +167,11 @@ private static RubyClass getLazyCreatedSingletonClass(RubyContext context, RubyC
209
167
@ TruffleBoundary
210
168
private static RubyClass createSingletonClass (RubyContext context , RubyClass rubyClass ) {
211
169
final RubyClass singletonSuperclass ;
212
- final RubyClass superclass = getSuperClass ( rubyClass ) ;
213
- if (superclass == null ) {
170
+ final Object superclass = rubyClass . superclass ;
171
+ if (superclass == nil ) {
214
172
singletonSuperclass = rubyClass .getLogicalClass ();
215
173
} else {
216
- singletonSuperclass = getLazyCreatedSingletonClass (context , superclass );
174
+ singletonSuperclass = getLazyCreatedSingletonClass (context , ( RubyClass ) superclass );
217
175
}
218
176
219
177
RubyClass metaClass = ClassNodes .createRubyClass (
@@ -236,15 +194,47 @@ private static RubyClass getClassClass(RubyClass rubyClass) {
236
194
return rubyClass .getLogicalClass ();
237
195
}
238
196
239
- @ TruffleBoundary
240
- public static RubyClass getSuperClass (RubyClass rubyClass ) {
241
- for (RubyModule ancestor : rubyClass .fields .ancestors ()) {
242
- if (ancestor instanceof RubyClass && ancestor != rubyClass ) {
243
- return (RubyClass ) ancestor ;
197
+ @ Primitive (name = "class_new" )
198
+ public abstract static class NewClassNode extends PrimitiveArrayArgumentsNode {
199
+
200
+ @ Child private InitializeClassNode initializeClassNode ;
201
+ private final BranchProfile errorProfile = BranchProfile .create ();
202
+
203
+ @ Specialization
204
+ protected RubyClass newClass (RubyClass superclass , boolean callInherited , Object maybeBlock ) {
205
+ if (superclass .isSingleton ) {
206
+ errorProfile .enter ();
207
+ throw new RaiseException (getContext (), coreExceptions ().typeErrorSubclassSingletonClass (this ));
208
+ }
209
+ if (superclass == coreLibrary ().classClass ) {
210
+ errorProfile .enter ();
211
+ throw new RaiseException (getContext (), coreExceptions ().typeErrorSubclassClass (this ));
212
+ }
213
+
214
+ final RubyClass newRubyClass = new RubyClass (
215
+ coreLibrary ().classClass ,
216
+ getLanguage (),
217
+ getEncapsulatingSourceSection (),
218
+ null ,
219
+ null ,
220
+ false ,
221
+ null ,
222
+ superclass );
223
+
224
+ if (initializeClassNode == null ) {
225
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
226
+ initializeClassNode = insert (InitializeClassNodeGen .create ());
244
227
}
228
+
229
+ initializeClassNode .executeInitialize (newRubyClass , superclass , callInherited , maybeBlock );
230
+
231
+ return newRubyClass ;
245
232
}
246
233
247
- return null ;
234
+ @ Specialization (guards = "!isRubyClass(superclass)" )
235
+ protected RubyClass newClass (Object superclass , boolean callInherited , Object maybeBlock ) {
236
+ throw new RaiseException (getContext (), coreExceptions ().typeErrorSuperclassMustBeClass (this ));
237
+ }
248
238
}
249
239
250
240
/** #allocate should only be defined as an instance method of Class (Class#allocate), which is required for
@@ -293,78 +283,38 @@ protected RubyClass newSingletonInstance(
293
283
}
294
284
}
295
285
296
- @ CoreMethod (names = "initialize" , optional = 1 , needsBlock = true )
297
- public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {
298
-
299
- @ Child private InitializeClassNode initializeClassNode ;
300
286
287
+ @ CoreMethod (names = "initialize" , optional = 1 )
288
+ public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {
301
289
@ Specialization
302
- protected RubyClass initialize (RubyClass rubyClass , Object maybeSuperclass , Object maybeBlock ) {
303
- if (initializeClassNode == null ) {
304
- CompilerDirectives .transferToInterpreterAndInvalidate ();
305
- initializeClassNode = insert (InitializeClassNodeGen .create (true ));
306
- }
307
-
308
- return initializeClassNode .executeInitialize (rubyClass , maybeSuperclass , maybeBlock );
290
+ protected Object initialize (RubyClass rubyClass , Object maybeSuperclass ) {
291
+ throw new RaiseException (
292
+ getContext (),
293
+ getContext ().getCoreExceptions ().typeErrorAlreadyInitializedClass (this ));
309
294
}
310
-
311
295
}
312
296
313
297
@ CoreMethod (names = "inherited" , needsSelf = false , required = 1 , visibility = Visibility .PRIVATE )
314
298
public abstract static class InheritedNode extends CoreMethodArrayArgumentsNode {
315
-
316
299
@ Specialization
317
300
protected Object inherited (Object subclass ) {
318
301
return nil ;
319
302
}
320
-
321
303
}
322
304
323
305
@ CoreMethod (names = "superclass" )
324
306
public abstract static class SuperClassNode extends CoreMethodArrayArgumentsNode {
325
-
326
- @ Specialization (
327
- guards = { "rubyClass == cachedRubyClass" , "cachedSuperclass != null" },
328
- limit = "getCacheLimit()" )
329
- protected Object getSuperClass (RubyClass rubyClass ,
330
- @ Cached ("rubyClass" ) RubyClass cachedRubyClass ,
331
- @ Cached ("fastLookUp(cachedRubyClass)" ) Object cachedSuperclass ) {
332
- // caches only initialized classes, just allocated will go through slow look up
333
- return cachedSuperclass ;
334
- }
335
-
336
- @ Specialization (replaces = "getSuperClass" )
337
- protected Object getSuperClassUncached (RubyClass rubyClass ,
338
- @ Cached BranchProfile errorProfile ) {
339
- final Object superclass = fastLookUp (rubyClass );
340
- if (superclass != null ) {
341
- return superclass ;
342
- } else {
343
- errorProfile .enter ();
344
- throw new RaiseException (
345
- getContext (),
346
- getContext ().getCoreExceptions ().typeError ("uninitialized class" , this ));
347
- }
348
- }
349
-
350
- protected Object fastLookUp (RubyClass rubyClass ) {
307
+ @ Specialization
308
+ protected Object getSuperClass (RubyClass rubyClass ) {
351
309
return rubyClass .superclass ;
352
310
}
353
-
354
- protected int getCacheLimit () {
355
- return getLanguage ().options .CLASS_CACHE ;
356
- }
357
311
}
358
312
359
313
@ CoreMethod (names = { "__allocate__" , "__layout_allocate__" }, constructor = true , visibility = Visibility .PRIVATE )
360
- public abstract static class AllocateClassNode extends CoreMethodArrayArgumentsNode {
361
-
314
+ public abstract static class AllocateNode extends UnaryCoreMethodNode {
362
315
@ Specialization
363
- protected RubyClass allocate (RubyClass classClass ) {
364
- return createUninitializedRubyClass (
365
- getContext (),
366
- getEncapsulatingSourceSection (),
367
- classClass );
316
+ protected Object allocate (RubyClass rubyClass ) {
317
+ throw new RaiseException (getContext (), coreExceptions ().typeErrorAllocatorUndefinedFor (rubyClass , this ));
368
318
}
369
319
}
370
320
}
0 commit comments