[macruby-changes] [5236] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Feb 21 19:14:56 PST 2011
Revision: 5236
http://trac.macosforge.org/projects/ruby/changeset/5236
Author: lsansonetti at apple.com
Date: 2011-02-21 19:14:53 -0800 (Mon, 21 Feb 2011)
Log Message:
-----------
fix lexical const lookup bugs inside modules defined using the :: notation + attach necessary dwarf metadata to const lookup primitive calls in order for const_missing to properly appear in backtraces
Modified Paths:
--------------
MacRuby/trunk/compiler.cpp
MacRuby/trunk/compiler.h
MacRuby/trunk/kernel.c
MacRuby/trunk/spec/frozen/tags/macruby/language/constants_tags.txt
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/compiler.cpp 2011-02-22 03:14:53 UTC (rev 5236)
@@ -75,7 +75,8 @@
__save_state(PHINode *, ensure_pn);\
__save_state(NODE *, ensure_node);\
__save_state(bool, block_declaration);\
- __save_state(AllocaInst *, dispatch_argv);
+ __save_state(AllocaInst *, dispatch_argv);\
+ __save_state(uint64_t, outer_mask);
#define restore_compiler_state() \
__restore_state(current_line);\
@@ -109,7 +110,8 @@
__restore_state(ensure_pn);\
__restore_state(ensure_node);\
__restore_state(block_declaration);\
- __restore_state(dispatch_argv);
+ __restore_state(dispatch_argv);\
+ __restore_state(outer_mask);
#define reset_compiler_state() \
bb = NULL;\
@@ -142,7 +144,8 @@
ensure_pn = NULL;\
ensure_node = NULL;\
block_declaration = false;\
- dispatch_argv = NULL;
+ dispatch_argv = NULL;\
+ outer_mask = 0;
RoxorCompiler::RoxorCompiler(bool _debug_mode)
{
@@ -1510,7 +1513,7 @@
}
else {
assert(node->nd_else != NULL);
- args[0] = compile_class_path(node->nd_else, &flags);
+ args[0] = compile_class_path(node->nd_else, &flags, NULL);
assert(node->nd_else->nd_mid > 0);
args[1] = compile_id(node->nd_else->nd_mid);
}
@@ -1612,11 +1615,14 @@
Value *args[] = {
outer,
+ ConstantInt::get(Int64Ty, outer_mask),
compile_ccache(id),
compile_id(id),
ConstantInt::get(Int32Ty, flags)
};
- return compile_protected_call(getConstFunc, args, args + 4);
+ Instruction *insn = compile_protected_call(getConstFunc, args, args + 5);
+ attach_current_line_metadata(insn);
+ return insn;
}
Value *
@@ -2067,13 +2073,16 @@
}
Value *
-RoxorCompiler::compile_class_path(NODE *node, int *flags)
+RoxorCompiler::compile_class_path(NODE *node, int *flags, int *outer_level)
{
if (nd_type(node) == NODE_COLON3) {
// ::Foo
if (flags != NULL) {
*flags = 0;
}
+ if (outer_level != NULL) {
+ *outer_level = 0;
+ }
return compile_nsobject();
}
else if (node->nd_head != NULL) {
@@ -2081,12 +2090,23 @@
if (flags != NULL) {
*flags = DEFINE_SUB_OUTER;
}
+ if (outer_level != NULL) {
+ // Count the number of outers minus the current one.
+ int level = 0;
+ for (NODE *n = node; n != NULL; n = n->nd_next) {
+ level++;
+ }
+ *outer_level = level + 1;
+ }
return compile_node(node->nd_head);
}
else {
if (flags != NULL) {
*flags = DEFINE_OUTER;
}
+ if (outer_level != NULL) {
+ *outer_level = 0;
+ }
return compile_current_class();
}
}
@@ -3842,7 +3862,8 @@
{
assert(node->nd_cpath != NULL);
- Value *classVal;
+ Value *classVal = NULL;
+ int current_outer_level = 0;
if (nd_type(node) == NODE_SCLASS) {
classVal =
compile_singleton_class(compile_node(node->nd_recv));
@@ -3865,7 +3886,8 @@
}
int flags = 0;
- Value *cpath = compile_class_path(node->nd_cpath, &flags);
+ Value *cpath = compile_class_path(node->nd_cpath, &flags,
+ ¤t_outer_level);
if (nd_type(node) == NODE_MODULE) {
flags |= DEFINE_MODULE;
}
@@ -3914,6 +3936,17 @@
= ivars_slots_cache;
old_ivars_slots_cache.clear();
+ uint64_t old_outer_mask = outer_mask;
+ if (current_outer_level > 0) {
+ outer_mask <<= current_outer_level;
+ for (int i = 0; i < current_outer_level; i++) {
+ outer_mask |= (1 << i + 1);
+ }
+ }
+ else {
+ outer_mask <<= 1;
+ }
+
DEBUG_LEVEL_INC();
Value *val = compile_node(body);
assert(Function::classof(val));
@@ -3921,6 +3954,8 @@
GET_CORE()->optimize(f);
DEBUG_LEVEL_DEC();
+ outer_mask = old_outer_mask;
+
ivars_slots_cache = old_ivars_slots_cache;
block_declaration = old_block_declaration;
@@ -4635,13 +4670,13 @@
{
assert(node->nd_mid > 0);
if (rb_is_const_id(node->nd_mid)) {
- // Constant
+ // Constant.
assert(node->nd_head != NULL);
return compile_const(node->nd_mid,
compile_node(node->nd_head));
}
else {
- // Method call
+ // Method call.
abort(); // TODO
}
}
Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/compiler.h 2011-02-22 03:14:53 UTC (rev 5236)
@@ -143,6 +143,7 @@
int return_from_block_ids;
bool block_declaration;
AllocaInst *dispatch_argv;
+ long outer_mask;
Function *writeBarrierFunc;
Function *dispatchFunc;
@@ -381,7 +382,7 @@
Value *compile_current_class(void);
virtual Value *compile_nsobject(void);
virtual Value *compile_standarderror(void);
- Value *compile_class_path(NODE *node, int *flags);
+ Value *compile_class_path(NODE *node, int *flags, int *outer_level);
Value *compile_const(ID id, Value *outer);
Value *compile_singleton_class(Value *obj);
Value *compile_defined_expression(NODE *node);
Modified: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/kernel.c 2011-02-22 03:14:53 UTC (rev 5236)
@@ -139,9 +139,10 @@
}
PRIMITIVE VALUE
-vm_get_const(VALUE outer, void *cache_p, ID path, int flags)
+vm_get_const(VALUE outer, uint64_t outer_mask, void *cache_p, ID path,
+ int flags)
{
- struct ccache *cache = (struct ccache *) cache_p;
+ struct ccache *cache = (struct ccache *)cache_p;
const bool lexical_lookup = (flags & CONST_LOOKUP_LEXICAL);
const bool dynamic_class = (flags & CONST_LOOKUP_DYNAMIC_CLASS);
@@ -153,15 +154,17 @@
}
VALUE val;
- if (cache->outer == outer && cache->val != Qundef) {
+ if (cache->outer == outer && cache->outer_mask == outer_mask
+ && cache->val != Qundef) {
val = cache->val;
}
else {
- val = rb_vm_const_lookup(outer, path, lexical_lookup, false);
+ val = rb_vm_const_lookup_level(outer, outer_mask, path,
+ lexical_lookup, false);
cache->outer = outer;
+ cache->outer_mask = outer_mask;
cache->val = val;
}
-
return val;
}
Modified: MacRuby/trunk/spec/frozen/tags/macruby/language/constants_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/language/constants_tags.txt 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/spec/frozen/tags/macruby/language/constants_tags.txt 2011-02-22 03:14:53 UTC (rev 5236)
@@ -1,5 +1,2 @@
fails:Constant resolution within methods with statically assigned constants searches Object as a lexical scope only if Object is explicitly opened
-fails:Constant resolution within methods with statically assigned constants does not search the lexical scope of qualifying modules
fails:Constant resolution within methods with dynamically assigned constants searches Object as a lexical scope only if Object is explicitly opened
-fails:Constant resolution within methods with dynamically assigned constants does not search the lexical scope of qualifying modules
-fails:Constant resolution within methods with dynamically assigned constants searches the lexical scope of a block
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/vm.cpp 2011-02-22 03:14:53 UTC (rev 5236)
@@ -762,6 +762,7 @@
if (iter == ccache.end()) {
struct ccache *cache = (struct ccache *)malloc(sizeof(struct ccache));
cache->outer = 0;
+ cache->outer_mask = 0;
cache->val = Qundef;
ccache[path] = cache;
return cache;
@@ -1233,21 +1234,31 @@
extern "C"
VALUE
-rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined)
+rb_vm_const_lookup_level(VALUE outer, uint64_t outer_mask, ID path,
+ bool lexical, bool defined)
{
rb_vm_check_if_module(outer);
+
if (lexical) {
// Let's do a lexical lookup before a hierarchical one, by looking for
// the given constant in all modules under the given outer.
GET_CORE()->lock();
struct rb_vm_outer *o = GET_CORE()->get_outer((Class)outer);
+ uint64_t n = 0;
while (o != NULL && o->klass != (Class)rb_cNSObject) {
- VALUE val = rb_const_get_direct((VALUE)o->klass, path);
- if (val != Qundef) {
- GET_CORE()->unlock();
- return defined ? Qtrue : val;
+ // If the current outer isn't in the mask, it means we can use it
+ // for const lookup. The outer mask is used when performing const
+ // lookups inside modules defined using the :: notation
+ // (ex: class A::B; class C; class D::E; ...)
+ if (!(outer_mask & (1 << n))) {
+ VALUE val = rb_const_get_direct((VALUE)o->klass, path);
+ if (val != Qundef) {
+ GET_CORE()->unlock();
+ return defined ? Qtrue : val;
+ }
}
o = o->outer;
+ n++;
}
GET_CORE()->unlock();
}
@@ -1360,25 +1371,6 @@
}
}
- // Prepare the constant outer.
- VALUE const_outer;
- if (flags & DEFINE_OUTER) {
- const_outer = outer;
- }
- else if (flags & DEFINE_SUB_OUTER) {
- // The Foo::Bar case, the outer here is the outer of the outer.
- rb_vm_outer_t *o = GET_CORE()->get_outer((Class)outer);
- if (o != NULL && o->outer != NULL) {
- const_outer = (VALUE)o->outer->klass;
- }
- else {
- const_outer = rb_cObject;
- }
- }
- else {
- const_outer = rb_cObject;
- }
-
VALUE klass = get_klass_const(outer, path, dynamic_class);
if (klass != Qundef) {
// Constant is already defined.
@@ -1388,9 +1380,17 @@
rb_class2name(klass));
}
}
- rb_vm_set_outer(klass, const_outer);
}
else {
+ // Prepare the constant outer.
+ VALUE const_outer;
+ if ((flags & DEFINE_OUTER) || (flags & DEFINE_SUB_OUTER)) {
+ const_outer = outer;
+ }
+ else {
+ const_outer = rb_cObject;
+ }
+
// Define the constant.
if (flags & DEFINE_MODULE) {
assert(super == 0);
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2011-02-19 11:27:24 UTC (rev 5235)
+++ MacRuby/trunk/vm.h 2011-02-22 03:14:53 UTC (rev 5236)
@@ -319,7 +319,15 @@
VALUE rb_vm_top_self(void);
void rb_vm_const_is_defined(ID path);
VALUE rb_vm_resolve_const_value(VALUE val, VALUE klass, ID name);
-VALUE rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined);
+
+VALUE rb_vm_const_lookup_level(VALUE outer, uint64_t outer_mask, ID path,
+ bool lexical, bool defined);
+static inline VALUE
+rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined)
+{
+ return rb_vm_const_lookup_level(outer, 0, path, lexical, defined);
+}
+
bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
rb_vm_method_node_t **pnode);
bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
@@ -564,6 +572,7 @@
struct ccache {
VALUE outer;
+ uint64_t outer_mask;
VALUE val;
};
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20110221/c9cb6769/attachment-0001.html>
More information about the macruby-changes
mailing list