Permalink
Browse files

fixing bugs in instance_eval & friends + fixed some specs so that the…

…y pass under both 1.8 and 1.9

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2363 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent a745089 commit 12a1d67fd1b16d62c18f9ed624ffc11f68ade80c @lrz lrz committed Aug 25, 2009
View
8 class.c
@@ -1052,7 +1052,13 @@ rb_singleton_class(VALUE obj)
break;
default:
- klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+ if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
+ rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
+ klass = RBASIC(obj)->klass;
+ }
+ else {
+ klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+ }
break;
}
}
View
101 compiler.cpp
@@ -43,6 +43,7 @@ RoxorCompiler::RoxorCompiler(void)
current_block_node = NULL;
current_block_func = NULL;
current_opened_class = NULL;
+ dynamic_class = false;
current_module = false;
current_loop_begin_bb = NULL;
current_loop_body_bb = NULL;
@@ -627,11 +628,11 @@ RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
}
void
-RoxorCompiler::compile_prepare_method(Value *classVal, bool singleton,
- Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
+ bool singleton, Function *new_function, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method(Class klass, unsigned char singleton,
+ // void rb_vm_prepare_method(Class klass, unsigned char dynamic_class,
// SEL sel, Function *func, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
@@ -643,7 +644,8 @@ RoxorCompiler::compile_prepare_method(Value *classVal, bool singleton,
std::vector<Value *> params;
params.push_back(classVal);
- params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ !singleton && dynamic_class ? 1 : 0));
params.push_back(sel);
params.push_back(compile_const_pointer(new_function));
@@ -656,11 +658,11 @@ RoxorCompiler::compile_prepare_method(Value *classVal, bool singleton,
}
void
-RoxorAOTCompiler::compile_prepare_method(Value *classVal, bool singleton,
- Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
+ bool singleton, Function *new_function, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method2(Class klass, unsigned char singleton,
+ // void rb_vm_prepare_method2(Class klass, unsigned char dynamic_class,
// SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
@@ -672,7 +674,8 @@ RoxorAOTCompiler::compile_prepare_method(Value *classVal, bool singleton,
std::vector<Value *> params;
params.push_back(classVal);
- params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ !singleton && dynamic_class ? 1 : 0));
params.push_back(sel);
// Make sure the function is compiled before use, this way LLVM won't use
@@ -1134,17 +1137,20 @@ Value *
RoxorCompiler::compile_cvar_get(ID id, bool check)
{
if (cvarGetFunc == NULL) {
- // VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check);
+ // VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
+ // unsigned char dynamic_class);
cvarGetFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_cvar_get",
- RubyObjTy, RubyObjTy, IntTy, Type::Int8Ty, NULL));
+ RubyObjTy, RubyObjTy, IntTy, Type::Int8Ty, Type::Int8Ty,
+ NULL));
}
std::vector<Value *> params;
params.push_back(compile_current_class());
params.push_back(compile_id(id));
params.push_back(ConstantInt::get(Type::Int8Ty, check ? 1 : 0));
+ params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
return compile_protected_call(cvarGetFunc, params);
}
@@ -1153,17 +1159,19 @@ Value *
RoxorCompiler::compile_cvar_assignment(ID name, Value *val)
{
if (cvarSetFunc == NULL) {
- // VALUE rb_vm_cvar_set(VALUE klass, ID id, VALUE val);
+ // VALUE rb_vm_cvar_set(VALUE klass, ID id, VALUE val,
+ // unsigned char dynamic_class);
cvarSetFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_cvar_set",
- RubyObjTy, RubyObjTy, IntTy, RubyObjTy, NULL));
+ RubyObjTy, RubyObjTy, IntTy, RubyObjTy, Type::Int8Ty, NULL));
}
std::vector<Value *> params;
params.push_back(compile_current_class());
params.push_back(compile_id(name));
params.push_back(val);
+ params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
return CallInst::Create(cvarSetFunc, params.begin(),
params.end(), "", bb);
@@ -1192,26 +1200,30 @@ Value *
RoxorCompiler::compile_constant_declaration(NODE *node, Value *val)
{
if (setConstFunc == NULL) {
- // VALUE rb_vm_set_const(VALUE mod, ID id, VALUE obj);
+ // VALUE rb_vm_set_const(VALUE mod, ID id, VALUE obj,
+ // unsigned char dynamic_class);
setConstFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_set_const",
- Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, NULL));
+ Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, Type::Int8Ty,
+ NULL));
}
std::vector<Value *> params;
+ bool outer = false;
if (node->nd_vid > 0) {
params.push_back(compile_current_class());
params.push_back(compile_id(node->nd_vid));
}
else {
assert(node->nd_else != NULL);
- params.push_back(compile_class_path(node->nd_else, NULL));
+ params.push_back(compile_class_path(node->nd_else, &outer));
assert(node->nd_else->nd_mid > 0);
params.push_back(compile_id(node->nd_else->nd_mid));
}
-
params.push_back(val);
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ dynamic_class && outer ? 1 : 0));
CallInst::Create(setConstFunc, params.begin(), params.end(), "", bb);
@@ -1288,10 +1300,11 @@ RoxorCompiler::compile_const(ID id, Value *outer)
if (getConstFunc == NULL) {
// VALUE rb_vm_get_const(VALUE mod, unsigned char lexical_lookup,
- // struct ccache *cache, ID id);
+ // struct ccache *cache, ID id, unsigned char dynamic_class);
getConstFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_get_const",
- RubyObjTy, RubyObjTy, Type::Int8Ty, PtrTy, IntTy, NULL));
+ RubyObjTy, RubyObjTy, Type::Int8Ty, PtrTy, IntTy, Type::Int8Ty,
+ NULL));
}
std::vector<Value *> params;
@@ -1300,6 +1313,7 @@ RoxorCompiler::compile_const(ID id, Value *outer)
params.push_back(ConstantInt::get(Type::Int8Ty, outer_given ? 0 : 1));
params.push_back(compile_ccache(id));
params.push_back(compile_id(id));
+ params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
return compile_protected_call(getConstFunc, params);
}
@@ -3671,7 +3685,8 @@ RoxorCompiler::compile_node(NODE *node)
Value *classVal;
if (nd_type(node) == NODE_SCLASS) {
- classVal = compile_singleton_class(compile_node(node->nd_recv));
+ classVal =
+ compile_singleton_class(compile_node(node->nd_recv));
}
else {
assert(node->nd_cpath->nd_mid > 0);
@@ -3680,16 +3695,18 @@ RoxorCompiler::compile_node(NODE *node)
NODE *super = node->nd_super;
if (defineClassFunc == NULL) {
- // VALUE rb_vm_define_class(ID path, VALUE outer, VALUE super,
- // int flags);
- defineClassFunc = cast<Function>(module->getOrInsertFunction(
+ // VALUE rb_vm_define_class(ID path, VALUE outer,
+ // VALUE super, int flags,
+ // unsigned char dynamic_class);
+ defineClassFunc = cast<Function>(
+ module->getOrInsertFunction(
"rb_vm_define_class",
RubyObjTy, IntTy, RubyObjTy, RubyObjTy,
- Type::Int32Ty, NULL));
+ Type::Int32Ty, Type::Int8Ty, NULL));
}
std::vector<Value *> params;
- bool outer = true;
+ bool outer = false;
params.push_back(compile_id(path));
params.push_back(compile_class_path(node->nd_cpath, &outer));
@@ -3703,6 +3720,8 @@ RoxorCompiler::compile_node(NODE *node)
flags |= DEFINE_OUTER;
}
params.push_back(ConstantInt::get(Type::Int32Ty, flags));
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ outer && dynamic_class ? 1 : 0));
classVal = compile_protected_call(defineClassFunc, params);
}
@@ -3739,13 +3758,12 @@ RoxorCompiler::compile_node(NODE *node)
current_module = nd_type(node) == NODE_MODULE;
compile_set_current_scope(classVal, publicScope);
- Value *old_current_class =
- compile_set_current_class(
- ConstantInt::get(RubyObjTy, 0));
+ bool old_dynamic_class = dynamic_class;
+ dynamic_class = false;
Value *val = compile_node(body->nd_body);
- compile_set_current_class(old_current_class);
+ dynamic_class = old_dynamic_class;
compile_set_current_scope(classVal, defaultScope);
BasicBlock::InstListType &list = bb->getInstList();
@@ -4263,16 +4281,21 @@ RoxorCompiler::compile_node(NODE *node)
case NODE_ALIAS:
{
if (aliasFunc == NULL) {
- // void rb_vm_alias(VALUE outer, ID from, ID to);
- aliasFunc = cast<Function>(module->getOrInsertFunction("rb_vm_alias",
- Type::VoidTy, RubyObjTy, IntTy, IntTy, NULL));
+ // void rb_vm_alias2(VALUE outer, ID from, ID to,
+ // unsigned char dynamic_class);
+ aliasFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_alias2",
+ Type::VoidTy, RubyObjTy, IntTy, IntTy, Type::Int8Ty,
+ NULL));
}
std::vector<Value *> params;
params.push_back(compile_current_class());
params.push_back(compile_id(node->u1.node->u1.node->u2.id));
params.push_back(compile_id(node->u2.node->u1.node->u2.id));
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ dynamic_class ? 1 : 0));
compile_protected_call(aliasFunc, params);
@@ -4326,8 +4349,8 @@ RoxorCompiler::compile_node(NODE *node)
rb_vm_arity_t arity = rb_vm_node_arity(body);
const SEL sel = mid_to_sel(mid, arity.real);
- compile_prepare_method(classVal, singleton_method, compile_sel(sel),
- new_function, arity, body);
+ compile_prepare_method(classVal, compile_sel(sel),
+ singleton_method, new_function, arity, body);
return nilVal;
}
@@ -4336,11 +4359,13 @@ RoxorCompiler::compile_node(NODE *node)
case NODE_UNDEF:
{
if (undefFunc == NULL) {
- // VALUE rb_vm_undef(VALUE klass, ID name);
+ // VALUE rb_vm_undef(VALUE klass, ID name,
+ // unsigned char dynamic_class);
undefFunc =
cast<Function>(module->getOrInsertFunction(
"rb_vm_undef",
- Type::VoidTy, RubyObjTy, IntTy, NULL));
+ Type::VoidTy, RubyObjTy, IntTy, Type::Int8Ty,
+ NULL));
}
assert(node->u2.node != NULL);
@@ -4349,6 +4374,8 @@ RoxorCompiler::compile_node(NODE *node)
std::vector<Value *> params;
params.push_back(compile_current_class());
params.push_back(compile_id(name));
+ params.push_back(ConstantInt::get(Type::Int8Ty,
+ dynamic_class ? 1 : 0));
compile_protected_call(undefFunc, params);
@@ -4700,15 +4727,19 @@ RoxorCompiler::compile_node(NODE *node)
bool old_current_block_chain = current_block_chain;
int old_return_from_block = return_from_block;
BasicBlock *old_rescue_bb = rescue_bb;
+ bool old_dynamic_class = dynamic_class;
current_mid = 0;
current_block = true;
current_block_chain = true;
+ dynamic_class = true;
assert(node->nd_body != NULL);
Value *block = compile_node(node->nd_body);
assert(Function::classof(block));
+ dynamic_class = old_dynamic_class;
+
BasicBlock *return_from_block_bb = NULL;
if (!old_current_block_chain && return_from_block != -1) {
// The block we just compiled contains one or more
View
11 compiler.h
@@ -59,6 +59,8 @@ class RoxorCompiler {
bool is_inside_eval(void) { return inside_eval; }
void set_inside_eval(bool flag) { inside_eval = flag; }
+ bool is_dynamic_class(void) { return dynamic_class; }
+ void set_dynamic_class(bool flag) { dynamic_class = flag; }
protected:
const char *fname;
@@ -97,6 +99,7 @@ class RoxorCompiler {
NODE *current_block_node;
Function *current_block_func;
GlobalVariable *current_opened_class;
+ bool dynamic_class;
bool current_module;
BasicBlock *current_loop_begin_bb;
BasicBlock *current_loop_body_bb;
@@ -228,8 +231,8 @@ class RoxorCompiler {
BasicBlock *thenBB);
void compile_single_when_argument(NODE *arg, Value *comparedToVal,
BasicBlock *thenBB);
- virtual void compile_prepare_method(Value *classVal, bool singleton,
- Value *sel, Function *new_function, rb_vm_arity_t &arity,
+ virtual void compile_prepare_method(Value *classVal, Value *sel,
+ bool singleton, Function *new_function, rb_vm_arity_t &arity,
NODE *body);
Value *compile_dispatch_call(std::vector<Value *> &params);
Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
@@ -343,8 +346,8 @@ class RoxorAOTCompiler : public RoxorCompiler {
Value *compile_mcache(SEL sel, bool super);
Value *compile_ccache(ID id);
Instruction *compile_sel(SEL sel, bool add_to_bb=true);
- void compile_prepare_method(Value *classVal, bool singleton,
- Value *sel, Function *new_function, rb_vm_arity_t &arity,
+ void compile_prepare_method(Value *classVal, Value *sel,
+ bool singleton, Function *new_function, rb_vm_arity_t &arity,
NODE *body);
Value *compile_prepare_block_args(Function *func, int *flags);
Value *compile_nsobject(void);
View
2 load.c
@@ -290,7 +290,9 @@ rb_load(VALUE fname, int wrap)
if (node == NULL) {
rb_raise(rb_eSyntaxError, "compile error");
}
+ Class old_klass = rb_vm_set_current_class(NULL);
rb_vm_run(fname_str, node, NULL, false);
+ rb_vm_set_current_class(old_klass);
}
void
View
1 object.c
@@ -2852,6 +2852,7 @@ Init_Object(void)
rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
rb_set_class_path(rb_cObject, rb_cObject, "NSObject");
rb_cBasicObject = (VALUE)objc_duplicateClass((Class)rb_cObject, "BasicObject", 0);
+ rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
rb_cModule = boot_defclass("Module", rb_cNSObject);
rb_cClass = boot_defclass("Class", rb_cModule);
View
12 spec/frozen/core/class/inherited_spec.rb
@@ -37,36 +37,36 @@ def self.inherited(cls)
it "is called when marked as a private class method" do
CoreClassSpecs::A.private_class_method :inherited
CoreClassSpecs::Record.called?.should == nil
- module CoreClassSpecs; class B < A; end; end
+ module ::CoreClassSpecs; class B < A; end; end
CoreClassSpecs::Record.called?.should == CoreClassSpecs::B
end
it "is called when marked as a protected class method" do
- class << CoreClassSpecs::A
+ class << ::CoreClassSpecs::A
protected :inherited
end
CoreClassSpecs::Record.called?.should == nil
- module CoreClassSpecs; class C < A; end; end
+ module ::CoreClassSpecs; class C < A; end; end
CoreClassSpecs::Record.called?.should == CoreClassSpecs::C
end
it "is called when marked as a public class method" do
CoreClassSpecs::A.public_class_method :inherited
CoreClassSpecs::Record.called?.should == nil
- module CoreClassSpecs; class D < A; end; end
+ module ::CoreClassSpecs; class D < A; end; end
CoreClassSpecs::Record.called?.should == CoreClassSpecs::D
end
it "is called by super from a method provided by an included module" do
CoreClassSpecs::Record.called?.should == nil
- module CoreClassSpecs; class E < F; end; end
+ module ::CoreClassSpecs; class E < F; end; end
CoreClassSpecs::Record.called?.should == CoreClassSpecs::E
end
it "is called by super even when marked as a private class method" do
CoreClassSpecs::Record.called?.should == nil
CoreClassSpecs::H.private_class_method :inherited
- module CoreClassSpecs; class I < H; end; end
+ module ::CoreClassSpecs; class I < H; end; end
CoreClassSpecs::Record.called?.should == CoreClassSpecs::I
end
View
2 spec/frozen/core/kernel/eval_spec.rb
@@ -212,7 +212,7 @@ def c
it "should perform top level evaluations from inside a block" do
# The class Object bit is needed to workaround some mspec oddness
- class Object
+ class ::Object
[1].each { eval "Const = 1"}
Const.should == 1
remove_const :Const
View
34 spec/frozen/language/defined_spec.rb
@@ -177,19 +177,19 @@ module AAA
end
not_compliant_on :rubinius do
- # I (Evan) am not certain we'll support defined?(super) ever.
- # for now, i'm marking these as compliant.
- it "returns 'super' when Subclass#no_args uses defined?" do
- ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.no_args)
- ret.should == "super"
- end
-
- it "returns 'super' when Subclass#args uses defined?" do
- ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.args)
- ret.should == "super"
- end
-
ruby_version_is "" ... "1.9" do
+ # I (Evan) am not certain we'll support defined?(super) ever.
+ # for now, i'm marking these as compliant.
+ it "returns 'super' when Subclass#no_args uses defined?" do
+ ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.no_args)
+ ret.should == "super"
+ end
+
+ it "returns 'super' when Subclass#args uses defined?" do
+ ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.args)
+ ret.should == "super"
+ end
+
it "returns 'local-variable(in-block)' when defined? is called on a block var" do
block = Proc.new { |xxx| defined?(xxx) }
ret = block.call(1)
@@ -198,6 +198,16 @@ module AAA
end
ruby_version_is "1.9" do
+ it "returns 'super' when Subclass#no_args uses defined?" do
+ ret = (LanguageDefinedSubclass.new.no_args)
+ ret.should == "super"
+ end
+
+ it "returns 'super' when Subclass#args uses defined?" do
+ ret = (LanguageDefinedSubclass.new.args)
+ ret.should == "super"
+ end
+
it "returns 'local-variable' when defined? is called on a block var" do
block = Proc.new { |xxx| defined?(xxx) }
ret = block.call(1)
View
3 spec/frozen/tags/macruby/core/basicobject/instance_exec_tags.txt
@@ -1,4 +1,3 @@
-critical:BasicObject#instance_exec raises a LocalJumpError unless given a block
-fails:BasicObject#instance_exec only binds the exec to the receiver
fails:BasicObject#instance_exec raises a TypeError when defining methods on an immediate
fails:BasicObject#instance_exec raises a TypeError when defining methods on numerics
+fails:BasicObject#instance_exec sets class variables in the receiver
View
6 spec/frozen/tags/macruby/core/kernel/instance_eval_tags.txt
@@ -1,7 +1,3 @@
-critical:Kernel#instance_eval treats block-local variables as local to the block
-fails:Kernel#instance_eval passes the object to the block
-fails:Kernel#instance_eval only binds the eval to the receiver
-fails:Kernel#instance_eval shares a scope across sibling evals
-fails:Kernel#instance_eval sets class variables in the receiver
+fails:Kernel#instance_eval treats block-local variables as local to the block
fails:Kernel#instance_eval raises a TypeError when defining methods on an immediate
fails:Kernel#instance_eval raises a TypeError when defining methods on numerics
View
2 spec/frozen/tags/macruby/core/module/private_class_method_tags.txt
@@ -1,2 +0,0 @@
-fails:Module#private_class_method raises a NameError when the given name is not a method
-fails:Module#private_class_method raises a NameError when the given name is an instance method
View
1 spec/macruby/core/exception_spec.rb
@@ -1,5 +1,6 @@
require File.dirname(__FILE__) + "/../spec_helper"
FixtureCompiler.require! "exception"
+TestException # force dynamic load
=begin # TODO
describe "An Objective-C exception" do
View
1 spec/macruby/core/object_spec.rb
@@ -1,5 +1,6 @@
require File.dirname(__FILE__) + "/../spec_helper"
FixtureCompiler.require! "object"
+TestObject # force dynamic load
require File.join(FIXTURES, 'object')
View
178 vm.cpp
@@ -828,11 +828,13 @@ rb_vm_set_abort_on_exception(bool flag)
extern "C"
void
-rb_vm_set_const(VALUE outer, ID id, VALUE obj)
+rb_vm_set_const(VALUE outer, ID id, VALUE obj, unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- outer = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ outer = (VALUE)k;
+ }
}
rb_const_set(outer, id, obj);
GET_CORE()->const_defined(id);
@@ -890,11 +892,13 @@ rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined)
extern "C"
VALUE
rb_vm_get_const(VALUE outer, unsigned char lexical_lookup,
- struct ccache *cache, ID path)
+ struct ccache *cache, ID path, unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (lexical_lookup && k != NULL) {
- outer = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (lexical_lookup && k != NULL) {
+ outer = (VALUE)k;
+ }
}
assert(cache != NULL);
@@ -950,14 +954,17 @@ check_if_module(VALUE mod)
extern "C"
VALUE
-rb_vm_define_class(ID path, VALUE outer, VALUE super, int flags)
+rb_vm_define_class(ID path, VALUE outer, VALUE super, int flags,
+ unsigned char dynamic_class)
{
assert(path > 0);
check_if_module(outer);
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- outer = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ outer = (VALUE)k;
+ }
}
VALUE klass;
@@ -1023,6 +1030,7 @@ lle_X_rb_vm_define_class(const FunctionType *FT,
FROM_GV(Args[0], ID),
FROM_GV(Args[1], VALUE),
FROM_GV(Args[2], VALUE),
+ FROM_GV(Args[3], int),
FROM_GV(Args[3], unsigned char)));
}
@@ -1063,22 +1071,27 @@ rb_vm_ivar_set(VALUE obj, ID name, VALUE val, int *slot_cache)
extern "C"
VALUE
-rb_vm_cvar_get(VALUE klass, ID id, unsigned char check)
+rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
+ unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- klass = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ klass = (VALUE)k;
+ }
}
return rb_cvar_get2(klass, id, check);
}
extern "C"
VALUE
-rb_vm_cvar_set(VALUE klass, ID id, VALUE val)
+rb_vm_cvar_set(VALUE klass, ID id, VALUE val, unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- klass = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ klass = (VALUE)k;
+ }
}
rb_cvar_set(klass, id, val);
return val;
@@ -1157,11 +1170,13 @@ rb_vm_alias_method(Class klass, Method method, ID name, bool noargs)
extern "C"
void
-rb_vm_alias(VALUE outer, ID name, ID def)
+rb_vm_alias2(VALUE outer, ID name, ID def, unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- outer = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ outer = (VALUE)k;
+ }
}
rb_frozen_class_p(outer);
if (outer == rb_cObject) {
@@ -1193,11 +1208,20 @@ rb_vm_alias(VALUE outer, ID name, ID def)
extern "C"
void
-rb_vm_undef(VALUE klass, VALUE name)
+rb_vm_alias(VALUE outer, ID name, ID def)
+{
+ rb_vm_alias2(outer, name, def, false);
+}
+
+extern "C"
+void
+rb_vm_undef(VALUE klass, VALUE name, unsigned char dynamic_class)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- klass = (VALUE)k;
+ if (dynamic_class) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ klass = (VALUE)k;
+ }
}
rb_vm_undef_method((Class)klass, rb_to_id(name), true);
}
@@ -1477,10 +1501,10 @@ RoxorCore::prepare_method(Class klass, SEL sel, Function *func,
}
static void
-prepare_method(Class klass, bool singleton, SEL sel, void *data,
+prepare_method(Class klass, bool dynamic_class, SEL sel, void *data,
const rb_vm_arity_t &arity, int flags, bool precompiled)
{
- if (!singleton) {
+ if (dynamic_class) {
Class k = GET_VM()->get_current_class();
if (k != NULL) {
const bool meta = class_isMetaClass(klass);
@@ -1561,8 +1585,8 @@ prepare_method(Class klass, bool singleton, SEL sel, void *data,
for (i = 0; i < count; i++) {
VALUE mod = RARRAY_AT(included_in_classes, i);
rb_vm_set_current_scope(mod, SCOPE_PUBLIC);
- prepare_method((Class)mod, false, orig_sel, data, arity, flags,
- precompiled);
+ prepare_method((Class)mod, false, orig_sel, data, arity,
+ flags, precompiled);
rb_vm_set_current_scope(mod, SCOPE_DEFAULT);
}
}
@@ -1571,18 +1595,20 @@ prepare_method(Class klass, bool singleton, SEL sel, void *data,
extern "C"
void
-rb_vm_prepare_method(Class klass, bool singleton, SEL sel, Function *func,
- const rb_vm_arity_t arity, int flags)
+rb_vm_prepare_method(Class klass, unsigned char dynamic_class, SEL sel,
+ Function *func, const rb_vm_arity_t arity, int flags)
{
- prepare_method(klass, singleton, sel, (void *)func, arity, flags, false);
+ prepare_method(klass, dynamic_class, sel, (void *)func, arity,
+ flags, false);
}
extern "C"
void
-rb_vm_prepare_method2(Class klass, bool singleton, SEL sel, IMP ruby_imp,
- const rb_vm_arity_t arity, int flags)
+rb_vm_prepare_method2(Class klass, unsigned char dynamic_class, SEL sel,
+ IMP ruby_imp, const rb_vm_arity_t arity, int flags)
{
- prepare_method(klass, singleton, sel, (void *)ruby_imp, arity, flags, true);
+ prepare_method(klass, dynamic_class, sel, (void *)ruby_imp, arity,
+ flags, true);
}
static rb_vm_method_node_t * __rb_vm_define_method(Class klass, SEL sel,
@@ -2758,24 +2784,30 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
#endif
bool block_already_current = vm->is_block_current(block);
+ Class current_klass = vm->get_current_class();
if (!block_already_current) {
vm->add_current_block(block);
}
+ vm->set_current_class(NULL);
struct Finally {
bool block_already_current;
+ Class current_class;
RoxorVM *vm;
- Finally(bool _block_already_current, RoxorVM *_vm) {
+ Finally(bool _block_already_current, Class _current_class,
+ RoxorVM *_vm) {
block_already_current = _block_already_current;
+ current_class = _current_class;
vm = _vm;
}
~Finally() {
if (!block_already_current) {
vm->pop_current_block();
}
+ vm->set_current_class(current_class);
vm->pop_broken_with();
}
- } finalizer(block_already_current, vm);
+ } finalizer(block_already_current, current_klass, vm);
return __rb_vm_ruby_dispatch(self, sel, rcache.node, opt, argc, argv);
}
@@ -3322,9 +3354,10 @@ rb_vm_prepare_block(void *function, int flags, VALUE self, rb_vm_arity_t arity,
int dvars_size, ...)
{
assert(function != NULL);
+ RoxorVM *vm = GET_VM();
bool cached = false;
- rb_vm_block_t *b = GET_VM()->uncache_or_create_block(function, &cached,
+ rb_vm_block_t *b = vm->uncache_or_create_block(function, &cached,
dvars_size);
bool aot_block = false;
@@ -3361,6 +3394,7 @@ rb_vm_prepare_block(void *function, int flags, VALUE self, rb_vm_arity_t arity,
b->proc = Qnil;
b->self = self;
+ b->klass = (VALUE)vm->get_current_class();
b->parent_var_uses = parent_var_uses;
GC_WB(&b->parent_block, parent_block);
@@ -3779,6 +3813,7 @@ rb_vm_create_block_from_method(rb_vm_method_t *method)
b->proc = Qnil;
GC_WB(&b->self, method->recv);
+ b->klass = 0;
b->arity = method->node == NULL
? rb_vm_arity(method->arity) : method->node->arity;
b->imp = (IMP)method;
@@ -3808,6 +3843,7 @@ rb_vm_create_block_calling_sel(SEL sel)
rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+ sizeof(VALUE *));
+ b->klass = 0;
b->proc = Qnil;
b->arity = rb_vm_arity(1);
b->flags = VM_BLOCK_PROC;
@@ -3841,6 +3877,7 @@ rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+ (3 * sizeof(VALUE *)));
+ b->klass = 0;
b->proc = Qnil;
b->arity.min = 0;
b->arity.max = -1;
@@ -3922,11 +3959,24 @@ rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
}
b->flags |= VM_BLOCK_ACTIVE;
+ RoxorVM *vm = GET_VM();
+ Class old_current_class = vm->get_current_class();
+ vm->set_current_class((Class)b->klass);
+
struct Finally {
+ RoxorVM *vm;
rb_vm_block_t *b;
- Finally(rb_vm_block_t *_b) { b = _b; }
- ~Finally() { b->flags &= ~VM_BLOCK_ACTIVE; }
- } finalizer(b);
+ Class c;
+ Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _c) {
+ vm = _vm;
+ b = _b;
+ c = _c;
+ }
+ ~Finally() {
+ b->flags &= ~VM_BLOCK_ACTIVE;
+ vm->set_current_class(c);
+ }
+ } finalizer(vm, b, old_current_class);
if (b->flags & VM_BLOCK_METHOD) {
rb_vm_method_t *m = (rb_vm_method_t *)b->imp;
@@ -3966,8 +4016,13 @@ rb_vm_yield0(int argc, const VALUE *argv)
struct Finally {
RoxorVM *vm;
rb_vm_block_t *b;
- Finally(RoxorVM *_vm, rb_vm_block_t *_b) { vm = _vm; b = _b; }
- ~Finally() { vm->add_current_block(b); }
+ Finally(RoxorVM *_vm, rb_vm_block_t *_b) {
+ vm = _vm;
+ b = _b;
+ }
+ ~Finally() {
+ vm->add_current_block(b);
+ }
} finalizer(vm, b);
return rb_vm_block_eval0(b, b->self, argc, argv);
@@ -3990,20 +4045,15 @@ rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
VALUE old_self = b->self;
b->self = self;
- Class old_class = vm->get_current_class();
- if (klass == self) {
- // We only toggle the VM current klass in case #module_eval or
- // #class_eval is used (where the given klass and self objects are
- // actually the same instances).
- vm->set_current_class((Class)klass);
- }
+ VALUE old_class = b->klass;
+ b->klass = klass;
struct Finally {
RoxorVM *vm;
rb_vm_block_t *b;
- Class old_class;
+ VALUE old_class;
VALUE old_self;
- Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _old_class,
+ Finally(RoxorVM *_vm, rb_vm_block_t *_b, VALUE _old_class,
VALUE _old_self) {
vm = _vm;
b = _b;
@@ -4012,7 +4062,7 @@ rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
}
~Finally() {
b->self = old_self;
- vm->set_current_class(old_class);
+ b->klass = old_class;
vm->add_current_block(b);
}
} finalizer(vm, b, old_class, old_self);
@@ -4552,22 +4602,28 @@ VALUE
rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
rb_vm_binding_t *binding, bool inside_eval)
{
- VALUE old_top_object = GET_VM()->get_current_top_object();
+ RoxorVM *vm = GET_VM();
+ RoxorCompiler *compiler = RoxorCompiler::shared;
+
+ VALUE old_top_object = vm->get_current_top_object();
if (binding != NULL) {
self = binding->self;
}
if (self != 0) {
- GET_VM()->set_current_top_object(self);
+ vm->set_current_top_object(self);
}
Class old_class = GET_VM()->get_current_class();
+ bool old_dynamic_class = compiler->is_dynamic_class();
if (klass != 0) {
- GET_VM()->set_current_class((Class)klass);
+ vm->set_current_class((Class)klass);
+ compiler->set_dynamic_class(true);
}
VALUE val = rb_vm_run(fname, node, binding, inside_eval);
- GET_VM()->set_current_top_object(old_top_object);
- GET_VM()->set_current_class(old_class);
+ compiler->set_dynamic_class(old_dynamic_class);
+ vm->set_current_top_object(old_top_object);
+ vm->set_current_class(old_class);
return val;
}
View
3 vm.h
@@ -38,6 +38,7 @@ typedef struct rb_vm_local {
typedef struct rb_vm_block {
VALUE proc; // a reference to a Proc object, or nil
VALUE self;
+ VALUE klass;
VALUE userdata; // if VM_BLOCK_IFUNC, contains the user data, otherwise
// contains the key used in the blocks cache.
rb_vm_arity_t arity;
@@ -373,6 +374,8 @@ void rb_vm_thread_raise(rb_vm_thread_t *t, VALUE exc);
bool rb_vm_abort_on_exception(void);
void rb_vm_set_abort_on_exception(bool flag);
+Class rb_vm_set_current_class(Class klass);
+
bool rb_vm_is_multithreaded(void);
void rb_vm_set_multithreaded(bool flag);
View
3 vm_eval.c
@@ -534,6 +534,9 @@ rb_obj_instance_exec(VALUE self, SEL sel, int argc, VALUE *argv)
else {
klass = rb_singleton_class(self);
}
+ if (!rb_block_given_p()) {
+ rb_raise(rb_eLocalJumpError, "no block given");
+ }
return rb_vm_yield_under(klass, self, argc, argv);
}

0 comments on commit 12a1d67

Please sign in to comment.