217217import static org .jruby .api .Access .errnoModule ;
218218import static org .jruby .api .Access .loadService ;
219219import static org .jruby .api .Convert .asFixnum ;
220+ import static org .jruby .api .Convert .asSymbol ;
220221import static org .jruby .api .Create .newEmptyString ;
221222import static org .jruby .api .Create .newFrozenString ;
222223import static org .jruby .api .Error .*;
@@ -335,36 +336,35 @@ private Ruby(RubyInstanceConfig config) {
335336 classClass .setMetaClass (classClass );
336337 refinementClass .setMetaClass (classClass );
337338
338- RubyClass metaClass ;
339- metaClass = basicObjectClass .makeMetaClass (classClass ); // runtime needed for 3 things:
340- metaClass = objectClass .makeMetaClass (metaClass ); // 1. ObjectSpace
341- metaClass = moduleClass .makeMetaClass (metaClass ); // 2. Access 'Class' for makeMetaClass
342- classClass .makeMetaClass (metaClass ); // 3. booting check to ignore logging singletons
343- refinementClass .makeMetaClass (metaClass );
339+ var metaClass = basicObjectClass .makeMetaClassBootstrap (classClass , classClass );
340+ metaClass = objectClass .makeMetaClassBootstrap (metaClass , classClass );
341+ metaClass = moduleClass .makeMetaClassBootstrap (metaClass , classClass );
342+ classClass .makeMetaClassBootstrap (metaClass , classClass );
343+ refinementClass .makeMetaClassBootstrap (metaClass , classClass );
344344
345- RubyObject .createObjectClass (objectClass );
346- RubyModule .createModuleClass (moduleClass );
347- RubyClass .createClassClass (this , classClass );
345+ RubyObject .finishObjectClass (objectClass );
346+ RubyModule .finishModuleClass (moduleClass );
347+ RubyClass .finishClassClass (this , classClass );
348348
349349 // set constants now that they're initialized
350- basicObjectClass .setConstant ("BasicObject" , basicObjectClass ); // FIXME: We know these sets will work so make something primal
351- objectClass .setConstant ("BasicObject" , basicObjectClass ); // just for these (to remove all checks which would require
352- objectClass .setConstant ("Object" , objectClass ); // runtime.
353- objectClass .setConstant ("Class" , classClass );
354- objectClass .setConstant ("Module" , moduleClass );
355- objectClass .setConstant ("Refinement" , refinementClass );
350+ basicObjectClass .defineConstantBootstrap ("BasicObject" , basicObjectClass );
351+ objectClass .defineConstantBootstrap ("BasicObject" , basicObjectClass );
352+ objectClass .defineConstantBootstrap ("Object" , objectClass );
353+ objectClass .defineConstantBootstrap ("Class" , classClass );
354+ objectClass .defineConstantBootstrap ("Module" , moduleClass );
355+ objectClass .defineConstantBootstrap ("Refinement" , refinementClass );
356356
357357 // specializer for RubyObject subclasses
358358 objectSpecializer = new RubyObjectSpecializer (this );
359359
360- kernelModule = defineModuleUnder ("Kernel" , objectClass ); // Initialize Kernel and include into Object
360+ kernelModule = defineModuleBootstrap ("Kernel" ); // Initialize Kernel and include into Object
361361 topSelf = new RubyObject (this , objectClass ); // Object is ready, create top self
362362
363363 // nil, true, and false all are set in TC so they need to be created above (both class and instances).
364- // their methods are added afterwards since no dispatch happens until after first TC is defined.
365- nilClass = defineClass ("NilClass" , objectClass , NOT_ALLOCATABLE_ALLOCATOR );
366- falseClass = defineClass ("FalseClass" , objectClass , NOT_ALLOCATABLE_ALLOCATOR );
367- trueClass = defineClass ("TrueClass" , objectClass , NOT_ALLOCATABLE_ALLOCATOR );
364+ // their methods are added afterward since no dispatch happens until after first TC is defined.
365+ nilClass = defineClassBootstrap ("NilClass" );
366+ falseClass = defineClassBootstrap ("FalseClass" );
367+ trueClass = defineClassBootstrap ("TrueClass" );
368368
369369 nilObject = new RubyNil (this , nilClass );
370370 nilPrefilledArray = new IRubyObject [NIL_PREFILLED_ARRAY_SIZE ];
@@ -1389,24 +1389,6 @@ public RubyClass fastGetClass(String internedName) {
13891389 return getClass (internedName );
13901390 }
13911391
1392- /**
1393- * Define a new class under the Object namespace. Roughly equivalent to
1394- * rb_define_class in MRI. This is an internal API. Please use
1395- * {@link org.jruby.api.Define#defineClass(ThreadContext, String, RubyClass, ObjectAllocator)} instead.
1396- * For bootstrappin we still need a non-ThreadContext define for nil and boolean class definition
1397- * as they are required before we can initialize our topmost ThreadContext.
1398- *
1399- * @param name The name for the new class
1400- * @param superClass The super class for the new class
1401- * @param allocator An ObjectAllocator instance that can construct
1402- * instances of the new class.
1403- * @return The new class
1404- */
1405- @ Extension
1406- public RubyClass defineClass (String name , RubyClass superClass , ObjectAllocator allocator ) {
1407- return defineClassUnder (name , superClass , allocator , objectClass , null );
1408- }
1409-
14101392 /**
14111393 * A variation of defineClass that allows passing in an array of supplementary
14121394 * call sites for improving dynamic invocation performance.
@@ -1419,7 +1401,12 @@ public RubyClass defineClass(String name, RubyClass superClass, ObjectAllocator
14191401 */
14201402 @ Deprecated (since = "10.0" )
14211403 public RubyClass defineClass (String name , RubyClass superClass , ObjectAllocator allocator , CallSite [] callSites ) {
1422- return defineClassUnder (name , superClass , allocator , objectClass , callSites );
1404+ return defineClassUnder (getCurrentContext (), name , superClass , allocator , objectClass , callSites );
1405+ }
1406+
1407+ @ Deprecated (since = "10.0" )
1408+ public RubyClass defineClass (String name , RubyClass superClass , ObjectAllocator allocator ) {
1409+ return defineClassUnder (getCurrentContext (), name , superClass , allocator , objectClass , null );
14231410 }
14241411
14251412 /**
@@ -1440,15 +1427,20 @@ public RubyClass defineClass(String name, RubyClass superClass, ObjectAllocator
14401427 @ Extension
14411428 @ Deprecated (since = "10.0" )
14421429 public RubyClass defineClassUnder (String name , RubyClass superClass , ObjectAllocator allocator , RubyModule parent ) {
1443- return defineClassUnder (name , superClass , allocator , parent , null );
1430+ return defineClassUnder (runtimeError .getCurrentContext (), name , superClass , allocator , parent , null );
1431+ }
1432+
1433+ @ Deprecated (since = "10.0" )
1434+ public RubyClass defineClassUnder (String id , RubyClass superClass , ObjectAllocator allocator , RubyModule parent , CallSite [] callSites ) {
1435+ return defineClassUnder (getCurrentContext (), id , superClass , allocator , parent , callSites );
14441436 }
14451437
14461438 /**
14471439 * A variation of defineClassUnder that allows passing in an array of
14481440 * supplementary call sites to improve dynamic invocation. This is an internal API. Please
1449- * use {@link org.jruby.api.Define#defineClassUnder(ThreadContext, String, RubyClass, ObjectAllocator, RubyModule)}
1450- * or {@link org.jruby.RubyModule#defineClassUnder(ThreadContext, String, RubyClass, ObjectAllocator)} instead.
1441+ * use {@link org.jruby.RubyModule#defineClassUnder(ThreadContext, String, RubyClass, ObjectAllocator)} instead.
14511442 *
1443+ * @param context the current thread context
14521444 * @param id The name for the new class as an ISO-8859_1 String (id-value)
14531445 * @param superClass The super class for the new class
14541446 * @param allocator An ObjectAllocator instance that can construct
@@ -1457,32 +1449,38 @@ public RubyClass defineClassUnder(String name, RubyClass superClass, ObjectAlloc
14571449 * @param callSites The array of call sites to add
14581450 * @return The new class
14591451 */
1460- public RubyClass defineClassUnder (String id , RubyClass superClass , ObjectAllocator allocator , RubyModule parent , CallSite [] callSites ) {
1461- IRubyObject classObj = parent .getConstantAt (id );
1462-
1463- if (classObj != null ) {
1464- if (!(classObj instanceof RubyClass )) throw typeError (getCurrentContext (), str (this , ids (this , id ), " is not a class" ));
1465- RubyClass klazz = (RubyClass )classObj ;
1466- if (klazz .getSuperClass ().getRealClass () != superClass ) {
1467- throw newNameError (str (this , ids (this , id ), " is already defined" ), newSymbol (id ));
1468- }
1469- // If we define a class in Ruby, but later want to allow it to be defined in Java,
1470- // the allocator needs to be updated
1471- if (klazz .getAllocator () != allocator ) klazz .allocator (allocator );
1472- return klazz ;
1473- }
1452+ public RubyClass defineClassUnder (ThreadContext context , String id , RubyClass superClass , ObjectAllocator allocator ,
1453+ RubyModule parent , CallSite [] callSites ) {
1454+ IRubyObject object = parent .getConstantAt (id );
1455+ if (object != null ) return foundExistingClass (context , id , superClass , allocator , object );
14741456
14751457 boolean parentIsObject = parent == objectClass ;
14761458
1477- if (superClass == null ) {
1478- IRubyObject className = parentIsObject ? ids (this , id ) :
1479- parent .toRubyString (getCurrentContext ()).append (newString ("::" )).append (ids (this , id ));
1480- warn (getCurrentContext (), str (this , "no super class for '" , className , "', Object assumed" ));
1459+ if (superClass == null ) superClass = determineSuperClass (context , id , parent , parentIsObject );
1460+
1461+ return RubyClass .newClass (this , superClass , id , allocator , parent , !parentIsObject , callSites );
1462+ }
1463+
1464+ private RubyClass determineSuperClass (ThreadContext context , String id , RubyModule parent , boolean parentIsObject ) {
1465+ RubyClass superClass ;
1466+ IRubyObject className = parentIsObject ? ids (this , id ) :
1467+ parent .toRubyString (context ).append (newString ("::" )).append (ids (this , id ));
1468+ warn (context , str (this , "no super class for '" , className , "', Object assumed" ));
1469+
1470+ superClass = objectClass ;
1471+ return superClass ;
1472+ }
14811473
1482- superClass = objectClass ;
1474+ private RubyClass foundExistingClass (ThreadContext context , String id , RubyClass superClass , ObjectAllocator allocator , IRubyObject obj ) {
1475+ if (!(obj instanceof RubyClass klazz )) throw typeError (context , str (this , ids (this , id ), " is not a class" ));
1476+
1477+ if (klazz .getSuperClass ().getRealClass () != superClass ) {
1478+ throw newNameError (str (this , ids (this , id ), " is already defined" ), asSymbol (context , id ));
14831479 }
1480+ // If we define a class in Ruby, but later want to allow it to be defined in Java, the allocator needs to be updated
1481+ if (klazz .getAllocator () != allocator ) klazz .allocator (allocator );
14841482
1485- return RubyClass . newClass ( this , superClass , id , allocator , parent , ! parentIsObject , callSites ) ;
1483+ return klazz ;
14861484 }
14871485
14881486 /**
@@ -1495,7 +1493,32 @@ public RubyClass defineClassUnder(String id, RubyClass superClass, ObjectAllocat
14951493 @ Deprecated (since = "10.0" )
14961494 @ Extension
14971495 public RubyModule defineModule (String name ) {
1498- return defineModuleUnder (name , objectClass );
1496+ return defineModuleUnder (getCurrentContext (), name , objectClass );
1497+ }
1498+
1499+ /**
1500+ * This is only for defining nil,true,false. The reason we have this is so all other define methods
1501+ * can count on ThreadContext being available. These are defined before that point.
1502+ * @param name The name for the new class
1503+ * @return The new class
1504+ */
1505+ public RubyClass defineClassBootstrap (String name ) {
1506+ return RubyClass .newClass (this , objectClass , name , NOT_ALLOCATABLE_ALLOCATOR , objectClass , false , null );
1507+ }
1508+
1509+ /**
1510+ * This is only for defining kernel. The reason we have this is so all other define methods
1511+ * can count on ThreadContext being available. These are defined before that point.
1512+ * @param name The name for the new class
1513+ * @return The new module
1514+ */
1515+ public RubyModule defineModuleBootstrap (String name ) {
1516+ return RubyModule .newModule (this , name , objectClass , false );
1517+ }
1518+
1519+ @ Deprecated (since = "10.0" )
1520+ public RubyModule defineModuleUnder (String name , RubyModule parent ) {
1521+ return defineModuleUnder (getCurrentContext (), name , parent );
14991522 }
15001523
15011524 /**
@@ -1509,22 +1532,24 @@ public RubyModule defineModule(String name) {
15091532 * module
15101533 * @return The new module
15111534 */
1512- @ Extension
1513- public RubyModule defineModuleUnder (String name , RubyModule parent ) {
1535+ public RubyModule defineModuleUnder (ThreadContext context , String name , RubyModule parent ) {
15141536 IRubyObject moduleObj = parent .getConstantAt (name );
15151537
15161538 boolean parentIsObject = parent == objectClass ;
15171539
1518- if (moduleObj != null ) {
1519- if (moduleObj .isModule ()) return (RubyModule ) moduleObj ;
1540+ return moduleObj != null ?
1541+ foundExistingModule (context , parent , moduleObj , parentIsObject ) :
1542+ RubyModule .newModule (this , name , parent , !parentIsObject );
1543+ }
15201544
1521- RubyString typeName = parentIsObject ?
1522- types (this , moduleObj .getMetaClass ()) : types (this , parent , moduleObj .getMetaClass ());
1545+ private RubyModule foundExistingModule (ThreadContext context , RubyModule parent , IRubyObject moduleObj ,
1546+ boolean parentIsObject ) {
1547+ if (moduleObj .isModule ()) return (RubyModule ) moduleObj ;
15231548
1524- throw typeError ( getCurrentContext (), str ( this , typeName , " is not a module" ));
1525- }
1549+ RubyString typeName = parentIsObject ?
1550+ types ( this , moduleObj . getMetaClass ()) : types ( this , parent , moduleObj . getMetaClass ());
15261551
1527- return RubyModule . newModule ( this , name , parent , ! parentIsObject );
1552+ throw typeError ( context , str ( this , typeName , " is not a module" ) );
15281553 }
15291554
15301555 /**
0 commit comments