Skip to content

Commit

Permalink
Atomically initialize constants and class variables
Browse files Browse the repository at this point in the history
  • Loading branch information
waj committed Aug 21, 2019
1 parent 3e45cdb commit 573cdc7
Show file tree
Hide file tree
Showing 20 changed files with 235 additions and 110 deletions.
4 changes: 4 additions & 0 deletions spec/compiler/codegen/class_spec.cr
Expand Up @@ -447,6 +447,8 @@ describe "Code gen: class" do

it "allows using self in class scope" do
run(%(
require "prelude"
class Foo
def self.foo
1
Expand Down Expand Up @@ -713,6 +715,8 @@ describe "Code gen: class" do

it "codegens singleton (#718)" do
run(%(
require "prelude"
class Singleton
@@instance = new
Expand Down
24 changes: 20 additions & 4 deletions spec/compiler/codegen/class_var_spec.cr
Expand Up @@ -106,6 +106,8 @@ describe "Codegen: class var" do

it "uses var in class var initializer" do
run(%(
require "prelude"
class Foo
@@var : Int32
@@var = begin
Expand All @@ -128,6 +130,8 @@ describe "Codegen: class var" do

it "reads simple class var before another complex one" do
run(%(
require "prelude"
class Foo
@@var2 : Int32
@@var2 = @@var &+ 1
Expand All @@ -145,6 +149,8 @@ describe "Codegen: class var" do

it "initializes class var of union with single type" do
run(%(
require "prelude"
class Foo
@@var : Int32 | String
@@var = 42
Expand Down Expand Up @@ -196,6 +202,8 @@ describe "Codegen: class var" do

it "initializes dependent constant before class var" do
run(%(
require "prelude"
def foo
a = 1
b = 2
Expand Down Expand Up @@ -233,6 +241,8 @@ describe "Codegen: class var" do

it "doesn't use nilable type for initializer" do
run(%(
require "prelude"
class Foo
@@foo : Int32?
@@foo = 42
Expand All @@ -250,7 +260,9 @@ describe "Codegen: class var" do
end

it "codegens class var with begin and vars" do
run("
run(%(
require "prelude"
class Foo
@@foo : Int32
@@foo = begin
Expand All @@ -265,11 +277,13 @@ describe "Codegen: class var" do
end
Foo.foo
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "codegens class var with type declaration begin and vars" do
run("
run(%(
require "prelude"
class Foo
@@foo : Int32 = begin
a = 1
Expand All @@ -283,7 +297,7 @@ describe "Codegen: class var" do
end
Foo.foo
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "codegens class var with nilable reference type" do
Expand Down Expand Up @@ -338,6 +352,8 @@ describe "Codegen: class var" do

it "gets pointerof class var complex constant" do
run(%(
require "prelude"
z = Foo.foo
class Foo
Expand Down
80 changes: 70 additions & 10 deletions spec/compiler/codegen/const_spec.cr
Expand Up @@ -87,14 +87,18 @@ describe "Codegen: const" do

it "declare constants in right order" do
run(%(
require "prelude"
CONST1 = 1 + 1
CONST2 = true ? CONST1 : 0
CONST2
)).to_i.should eq(2)
end

it "uses correct types lookup" do
run("
run(%(
require "prelude"
module Moo
class B
def foo
Expand All @@ -110,11 +114,13 @@ describe "Codegen: const" do
end
foo
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "codegens variable assignment in const" do
run("
run(%(
require "prelude"
class Foo
def initialize(@x : Int32)
end
Expand All @@ -134,11 +140,13 @@ describe "Codegen: const" do
end
foo
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "declaring var" do
run("
run(%(
require "prelude"
BAR = begin
a = 1
while 1 == 2
Expand All @@ -153,7 +161,7 @@ describe "Codegen: const" do
end
Foo.new.compile
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "initialize const that might raise an exception" do
Expand All @@ -171,7 +179,9 @@ describe "Codegen: const" do
end

it "allows implicit self in constant, called from another class (bug)" do
run("
run(%(
require "prelude"
module Foo
def self.foo
1
Expand All @@ -187,11 +197,13 @@ describe "Codegen: const" do
end
Bar.new.bar
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "codegens two consts with same variable name" do
run("
run(%(
require "prelude"
CONST1 = begin
a = 1
end
Expand All @@ -201,11 +213,13 @@ describe "Codegen: const" do
end
(CONST1 + CONST2).to_i
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "works with variable declared inside if" do
run(%(
require "prelude"
FOO = begin
if 1 == 2
x = 3
Expand All @@ -220,6 +234,8 @@ describe "Codegen: const" do

it "codegens constant that refers to another constant that is a struct" do
run(%(
require "prelude"
struct Foo
X = Foo.new(1)
Y = X
Expand Down Expand Up @@ -281,6 +297,8 @@ describe "Codegen: const" do

it "uses const before declaring it (hoisting)" do
run(%(
require "prelude"
x = CONST
CONST = foo
Expand Down Expand Up @@ -342,6 +360,8 @@ describe "Codegen: const" do

it "gets pointerof constant" do
run(%(
require "prelude"
z = pointerof(FOO).value
FOO = 10
z
Expand All @@ -350,6 +370,8 @@ describe "Codegen: const" do

it "gets pointerof complex constant" do
run(%(
require "prelude"
z = pointerof(FOO).value
FOO = begin
a = 10
Expand Down Expand Up @@ -446,4 +468,42 @@ describe "Codegen: const" do

mod.to_s.should_not contain("CONST")
end

it "synchronize initialization of contants" do
run(%(
require "prelude"
def foo
v1, v2 = 1, 1
rand(100000..10000000).times do
v1, v2 = v2, v1 + v2
end
v2
end
ch = Channel(Int32).new
10.times do
spawn do
ch.send X
end
end
X = foo
def test(ch)
expected = X
10.times do
if ch.receive != expected
return false
end
end
true
end
test(ch)
)).to_b.should be_true
end
end
2 changes: 2 additions & 0 deletions spec/compiler/codegen/debug_spec.cr
Expand Up @@ -107,6 +107,8 @@ describe "Code gen: debug" do

it "has correct debug location after constant initialization in call with block (#4719)" do
codegen(%(
require "prelude"
fun __crystal_malloc_atomic(size : UInt32) : Void*
x = uninitialized Void*
x
Expand Down
6 changes: 4 additions & 2 deletions spec/compiler/codegen/hooks_spec.cr
Expand Up @@ -115,7 +115,9 @@ describe "Code gen: hooks" do
end

it "does inherited macro before class body" do
run("
run(%(
require "prelude"
class Global
@@x = 123
Expand All @@ -142,7 +144,7 @@ describe "Code gen: hooks" do
end
Bar.y
").to_i.should eq(123)
)).to_i.should eq(123)
end

it "does finished" do
Expand Down
4 changes: 4 additions & 0 deletions spec/compiler/codegen/macro_spec.cr
Expand Up @@ -663,6 +663,8 @@ describe "Code gen: macro" do

it "transforms hooks (bug)" do
codegen(%(
require "prelude"
module GC
def self.add_finalizer(object : T)
object.responds_to?(:finalize)
Expand Down Expand Up @@ -800,6 +802,8 @@ describe "Code gen: macro" do

it "copies base macro def to sub-subtype even after it was copied to a subtype (#448)" do
run(%(
require "prelude"
class Object
def class_name : String
{{@type.name.stringify}}
Expand Down
7 changes: 5 additions & 2 deletions spec/compiler/codegen/pointer_spec.cr
Expand Up @@ -250,10 +250,11 @@ describe "Code gen: pointer" do
end

it "gets pointer to constant" do
run("
run(%(
require "prelude"
FOO = 1
pointerof(FOO).value
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "passes pointer of pointer to method" do
Expand Down Expand Up @@ -324,6 +325,8 @@ describe "Code gen: pointer" do

it "does pointerof class variable with class" do
run(%(
require "prelude"
class Bar
def initialize(@x : Int32)
end
Expand Down
2 changes: 2 additions & 0 deletions spec/compiler/codegen/proc_spec.cr
Expand Up @@ -595,6 +595,8 @@ describe "Code gen: proc" do

it "codegens proc to implicit self in constant (#647)" do
run(%(
require "prelude"
module Foo
def self.blah
1
Expand Down

0 comments on commit 573cdc7

Please sign in to comment.