Permalink
Browse files

fixed a bug in the way we compile literal strings

  • Loading branch information...
1 parent 79466bf commit 913687b88c98dd55e45cfdc03c42e87c0317df59 @lrz lrz committed Jul 2, 2009
Showing with 74 additions and 7 deletions.
  1. +58 −6 compiler.cpp
  2. +8 −1 compiler.h
  3. +6 −0 string.c
  4. +2 −0 test_vm/literal.rb
View
@@ -101,6 +101,8 @@ RoxorCompiler::RoxorCompiler(const char *_fname)
masgnGetElemAfterSplatFunc = NULL;
masgnGetSplatFunc = NULL;
newStringFunc = NULL;
+ newString2Func = NULL;
+ newString3Func = NULL;
yieldFunc = NULL;
blockEvalFunc = NULL;
gvarSetFunc = NULL;
@@ -401,16 +403,16 @@ RoxorCompiler::compile_when_splat(Value *comparedToVal, Value *splatVal)
}
GlobalVariable *
-RoxorCompiler::compile_const_global_string(const char *str)
+RoxorCompiler::compile_const_global_string(const char *str, const size_t str_len)
{
- std::string s(str);
+ assert(str_len > 0);
+
+ std::string s(str, str_len);
std::map<std::string, GlobalVariable *>::iterator iter =
static_strings.find(s);
+
GlobalVariable *gvar;
if (iter == static_strings.end()) {
- const size_t str_len = strlen(str);
- assert(str_len > 0);
-
const ArrayType *str_type = ArrayType::get(Type::Int8Ty, str_len + 1);
std::vector<Constant *> ary_elements;
@@ -2393,6 +2395,56 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
return NULL;
}
+Value *
+RoxorCompiler::compile_literal(VALUE val)
+{
+ if (TYPE(val) == T_STRING) {
+ // We must compile a new string creation because strings are
+ // mutable, we can't simply compile a reference to a master
+ // copy.
+ //
+ // 10.times { s = 'foo'; s << 'bar' }
+ //
+ const char *str = RSTRING_PTR(val);
+ const size_t str_len = RSTRING_LEN(val);
+ if (str_len == 0) {
+ if (newString3Func == NULL) {
+ newString3Func = cast<Function>(
+ module->getOrInsertFunction(
+ "rb_str_new_empty", RubyObjTy, NULL));
+ }
+ return CallInst::Create(newString3Func, "", bb);
+ }
+ else {
+ GlobalVariable *str_gvar = compile_const_global_string(str,
+ str_len);
+
+ std::vector<Value *> idxs;
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ Instruction *load = GetElementPtrInst::Create(str_gvar,
+ idxs.begin(), idxs.end(), "", bb);
+
+ if (newString2Func == NULL) {
+ newString2Func = cast<Function>(
+ module->getOrInsertFunction(
+ "rb_str_new", RubyObjTy, PtrTy, Type::Int32Ty,
+ NULL));
+ }
+
+ std::vector<Value *> params;
+ params.push_back(load);
+ params.push_back(ConstantInt::get(Type::Int32Ty, str_len));
+
+ return compile_protected_call(newString2Func, params);
+ }
+ }
+
+ // The other types are supposedly immutables.
+ // TODO AOT compile!
+ return ConstantInt::get(RubyObjTy, (long)val);
+}
+
void
RoxorCompiler::compile_ivar_slots(Value *klass,
BasicBlock::InstListType &list,
@@ -3545,7 +3597,7 @@ RoxorCompiler::compile_node(NODE *node)
case NODE_STR:
{
assert(node->nd_lit != 0);
- return ConstantInt::get(RubyObjTy, (long)node->nd_lit);
+ return compile_literal(node->nd_lit);
}
break;
View
@@ -135,6 +135,8 @@ class RoxorCompiler {
Function *masgnGetElemAfterSplatFunc;
Function *masgnGetSplatFunc;
Function *newStringFunc;
+ Function *newString2Func;
+ Function *newString3Func;
Function *yieldFunc;
Function *blockEvalFunc;
Function *gvarSetFunc;
@@ -232,8 +234,13 @@ class RoxorCompiler {
return compile_const_pointer(sel, PtrTy, add_to_bb);
}
virtual Value *compile_id(ID id);
- GlobalVariable *compile_const_global_string(const char *str);
+ GlobalVariable *compile_const_global_string(const char *str,
+ const size_t str_len);
+ GlobalVariable *compile_const_global_string(const char *str) {
+ return compile_const_global_string(str, strlen(str));
+ }
Value *compile_arity(rb_vm_arity_t &arity);
+ Value *compile_literal(VALUE val);
void compile_landing_pad_header(void);
void compile_landing_pad_footer(void);
View
@@ -82,6 +82,12 @@ str_alloc(VALUE klass)
}
VALUE
+rb_str_new_empty(void)
+{
+ return str_alloc(0);
+}
+
+VALUE
rb_str_new_fast(int argc, ...)
{
VALUE str;
View
@@ -28,3 +28,5 @@
assert '42', "class Symbol; def !=(o); p 42; end; end; :foo != :foo"
assert "false", "p ['foo'] == [:foo]"
+
+assert '424242', "a=''; 3.times { b=''; b << '42'; a<<b }; p a.to_i"

0 comments on commit 913687b

Please sign in to comment.