-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
Conflicts: truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UnresolvedDispatchNode.java truffle/src/main/java/org/jruby/truffle/nodes/interop/InteropNode.java
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
- 9.1.2.0
- 9.1.1.0
- 9.1.0.0
- 9.0.5.0
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/dtd/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/dtd/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/dtd/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/dtd/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/dtd/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/formatters/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/formatters/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/formatters/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/light/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/parsers/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/validation/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/validation/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../../stdlib/rexml/validation/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/rexml/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../stdlib/xmlrpc' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require_relative '../../../stdlib/xmlrpc/' + File.basename(__FILE__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
fails:Encoding.locale_charmap returns a value based on the LC_ALL environment variable | ||
fails:Encoding.locale_charmap is unaffected by assigning to ENV['LC_ALL'] in the same process |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
fails:Enumerable#cycle passed no argument or nil loops indefinitely | ||
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be the result of multiplying the enumerable size by the argument passed | ||
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be zero when the argument passed is 0 or less | ||
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be Float::INFINITY when no argument is passed |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,7 @@ | ||
fails:"Proc#arity for instances created with -> () { } returns positive values for definition \n @a = -> (a:) { }\n @b = -> (a:, b:) { }\n @c = -> (a: 1, b:, c:, d: 2) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns positive values for definition \n @a = -> (a, b:) { }\n @b = -> (a, b:, &l) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns positive values for definition \n @a = -> (a, b, c:, d: 1) { }\n @b = -> (a, b, c:, d: 1, **k, &l) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns negative values for definition \n @a = -> (a: 1) { }\n @b = -> (a: 1, b: 2) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns negative values for definition \n @a = -> (a=1, b: 2) { }\n @b = -> (*a, b: 1) { }\n @c = -> (a=1, b: 2) { }\n @d = -> (a=1, *b, c: 2, &l) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns negative values for definition \n @a = -> (**k, &l) { }\n @b= -> (*a, **k) { }\n @c = ->(a: 1, b: 2, **k) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns negative values for definition \n @a = -> (a=1, *b, c:, d: 2, **k, &l) { }" | ||
fails:"Proc#arity for instances created with -> () { } returns negative values for definition \n @a = -> (a, b=1, *c, d, e:, f: 2, **k, &l) { }\n @b = -> (a, b=1, *c, d:, e:, f: 2, **k, &l) { }\n @c = -> (a=0, b=1, *c, d, e:, f: 2, **k, &l) { }\n @d = -> (a=0, b=1, *c, d:, e:, f: 2, **k, &l) { }" | ||
fails:"Proc#arity for instances created with lambda { || } returns positive values for definition \n @a = lambda { |a:| }\n @b = lambda { |a:, b:| }\n @c = lambda { |a: 1, b:, c:, d: 2| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns positive values for definition \n @a = lambda { |a, b:| }\n @b = lambda { |a, b:, &l| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns positive values for definition \n @a = lambda { |a, b, c:, d: 1| }\n @b = lambda { |a, b, c:, d: 1, **k, &l| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |a: 1| }\n @b = lambda { |a: 1, b: 2| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |a=1, b: 2| }\n @b = lambda { |*a, b: 1| }\n @c = lambda { |a=1, b: 2| }\n @d = lambda { |a=1, *b, c: 2, &l| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |**k, &l| }\n @b = lambda { |*a, **k| }\n @c = lambda { |a: 1, b: 2, **k| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |a=1, *b, c:, d: 2, **k, &l| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |(a, (*b, c)), d=1| }\n @b = lambda { |a, (*b, c), d, (*e), (*), **k| }\n @c = lambda { |a, (b, c), *, d:, e: 2, **| }" | ||
fails:"Proc#arity for instances created with lambda { || } returns negative values for definition \n @a = lambda { |a, b=1, *c, d, e:, f: 2, **k, &l| }\n @b = lambda { |a, b=1, *c, d:, e:, f: 2, **k, &l| }\n @c = lambda { |a=0, b=1, *c, d, e:, f: 2, **k, &l| }\n @d = lambda { |a=0, b=1, *c, d:, e:, f: 2, **k, &l| }" |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
fails:Symbol.all_symbols increases size of the return array when new symbol comes | ||
slow:Symbol.all_symbols returns an array containing all the Symbols in the symbol table | ||
slow:Symbol.all_symbols increases size of the return array when new symbol comes |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fails:REXML::Attributes#delete_all deletes all attributes that match name | ||
fails:REXML::Attributes#delete_all deletes all attributes that match name with a namespace | ||
fails:REXML::Attributes#delete_all returns the removed attribute |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Attributes#each_attribute iterates over the attributes yielding actual Attribute objects |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Attributes#each iterates over the attributes yielding expanded-name/value |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Attributes#[]= deletes an attribute is value is nil |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Attributes#length returns the number of attributes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Attributes#prefixes returns an array with the prefixes of each attribute | ||
fails:REXML::Attributes#prefixes does not include the default namespace |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Attributes#size returns the number of attributes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Attributes#to_a returns an array with the attributes | ||
fails:REXML::Attributes#to_a returns an empty array if it has no attributes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Document#clone clones document attributes | ||
fails:REXML::Document#clone clones document context |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Document#new can use other document context | ||
fails:REXML::Document#new clones source attributes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Element#add_element adds a child with name |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Element#attribute returns an attribute by name | ||
fails:REXML::Element#attribute supports attributes inside namespaces |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Element#attributes returns element's Attributes | ||
fails:REXML::Element#attributes returns an empty hash if element has no attributes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
fails:REXML::Element#clone creates a copy of element | ||
fails:REXML::Element#clone copies the attributes | ||
fails:REXML::Element#clone does not copy the text | ||
fails:REXML::Element#clone does not copy the child elements |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fails:REXML::Element#delete_namespace deletes a namespace from the element | ||
fails:REXML::Element#delete_namespace deletes default namespace when called with no args |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fails:REXML::Element#inspect returns the node as a string | ||
fails:REXML::Element#inspect inserts '...' if the node has children | ||
fails:REXML::Element#inspect inserts the attributes in the string |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
fails:REXML::Element#namespaces returns a hash of the namespaces | ||
fails:REXML::Element#namespaces returns an empty hash if no namespaces exist | ||
fails:REXML::Element#namespaces uses namespace prefixes as keys | ||
fails:REXML::Element#namespaces uses namespace values as the hash values |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fails:REXML::Element#new creates element from another element |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fails:REXML::Element#prefixes returns an array of the prefixes of the namespaces | ||
fails:REXML::Element#prefixes does not include the default namespace | ||
fails:REXML::Element#prefixes returns an empty array if no namespace was defined |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
exclude :test_condvar_wait_exception_handling, "not yet implemented" | ||
exclude :test_condvar_wait_deadlock_2, "timeout" | ||
exclude :test_condvar_wait_and_broadcast, "timeout" | ||
exclude :test_condvar_wait_deadlock, "spawn" | ||
exclude :test_dup, "needs investigation" | ||
exclude :test_dump, "Binding#eval" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/* | ||
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.nodes.core; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.nodes.Node; | ||
import com.oracle.truffle.api.object.*; | ||
import com.oracle.truffle.api.source.SourceSection; | ||
|
||
import org.jruby.truffle.nodes.objects.Allocator; | ||
import org.jruby.truffle.runtime.NotProvided; | ||
import org.jruby.truffle.runtime.RubyContext; | ||
import org.jruby.truffle.runtime.control.RaiseException; | ||
import org.jruby.truffle.runtime.core.RubyBasicObject; | ||
import org.jruby.truffle.runtime.core.RubyClass; | ||
import org.jruby.truffle.runtime.object.BasicObjectType; | ||
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock; | ||
|
||
import java.util.EnumSet; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
import java.util.concurrent.locks.Condition; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
@CoreClass(name = "ConditionVariable") | ||
public abstract class ConditionVariableNodes { | ||
|
||
private static class ConditionVariableType extends BasicObjectType { | ||
} | ||
|
||
public static final ConditionVariableType CONDITION_VARIABLE_TYPE = new ConditionVariableType(); | ||
|
||
private static final HiddenKey ASSOCIATED_MUTEX_IDENTIFIER = new HiddenKey("associated_mutex"); | ||
private static final Property ASSOCIATED_MUTEX_PROPERTY; | ||
private static final HiddenKey CONDITION_IDENTIFIER = new HiddenKey("condition"); | ||
private static final Property CONDITION_PROPERTY; | ||
private static final DynamicObjectFactory CONDITION_VARIABLE_FACTORY; | ||
|
||
static { | ||
Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator(); | ||
ASSOCIATED_MUTEX_PROPERTY = Property.create(ASSOCIATED_MUTEX_IDENTIFIER, | ||
allocator.locationForType(AtomicReference.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0); | ||
CONDITION_PROPERTY = Property.create(CONDITION_IDENTIFIER, | ||
allocator.locationForType(AtomicReference.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0); | ||
Shape shape = RubyBasicObject.LAYOUT.createShape(CONDITION_VARIABLE_TYPE) | ||
.addProperty(ASSOCIATED_MUTEX_PROPERTY) | ||
.addProperty(CONDITION_PROPERTY); | ||
CONDITION_VARIABLE_FACTORY = shape.createFactory(); | ||
} | ||
|
||
public static class ConditionVariableAllocator implements Allocator { | ||
@Override | ||
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) { | ||
return new RubyBasicObject(rubyClass, CONDITION_VARIABLE_FACTORY.newInstance(new AtomicReference<RubyBasicObject>(), new AtomicReference<Condition>())); | ||
} | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
protected static AtomicReference<RubyBasicObject> getAssociatedMutex(RubyBasicObject mutex) { | ||
assert mutex.getDynamicObject().getShape().hasProperty(ASSOCIATED_MUTEX_IDENTIFIER); | ||
return (AtomicReference<RubyBasicObject>) ASSOCIATED_MUTEX_PROPERTY.get(mutex.getDynamicObject(), true); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
protected static AtomicReference<Condition> getCondition(RubyBasicObject conditionVariable) { | ||
assert conditionVariable.getDynamicObject().getShape().hasProperty(CONDITION_IDENTIFIER); | ||
return (AtomicReference<Condition>) CONDITION_PROPERTY.get(conditionVariable.getDynamicObject(), true); | ||
} | ||
|
||
@CoreMethod(names = "broadcast") | ||
public abstract static class BroadcastNode extends UnaryCoreMethodNode { | ||
|
||
public BroadcastNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@Specialization | ||
public RubyBasicObject broadcast(RubyBasicObject conditionVariable) { | ||
final Condition condition = getCondition(conditionVariable).get(); | ||
final RubyBasicObject associatedMutex = getAssociatedMutex(conditionVariable).get(); | ||
|
||
if (condition == null) { | ||
return conditionVariable; | ||
} | ||
|
||
if (!MutexNodes.getLock(associatedMutex).isHeldByCurrentThread()) { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().threadError("Called ConditionVariable#broadcast without holding associated Mutex", this)); | ||
} | ||
|
||
condition.signalAll(); | ||
|
||
return conditionVariable; | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "signal") | ||
public abstract static class SignalNode extends UnaryCoreMethodNode { | ||
|
||
public SignalNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@Specialization | ||
public RubyBasicObject signal(RubyBasicObject conditionVariable) { | ||
final Condition condition = getCondition(conditionVariable).get(); | ||
final RubyBasicObject associatedMutex = getAssociatedMutex(conditionVariable).get(); | ||
|
||
if (condition == null) { | ||
return conditionVariable; | ||
} | ||
|
||
if (!MutexNodes.getLock(associatedMutex).isHeldByCurrentThread()) { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().threadError("Called ConditionVariable#signal without holding associated Mutex", this)); | ||
} | ||
|
||
condition.signal(); | ||
|
||
return conditionVariable; | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "wait", required = 1, optional = 1) | ||
public abstract static class WaitNode extends CoreMethodArrayArgumentsNode { | ||
|
||
public WaitNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
private static interface WaitAction { | ||
void wait(Condition condition) throws InterruptedException; | ||
} | ||
|
||
@Specialization(guards = "isRubyMutex(mutex)") | ||
RubyBasicObject wait(RubyBasicObject conditionVariable, RubyBasicObject mutex, NotProvided timeout) { | ||
return wait(conditionVariable, mutex, nil()); | ||
} | ||
|
||
@Specialization(guards = { "isRubyMutex(mutex)", "isNil(timeout)" }) | ||
RubyBasicObject wait(RubyBasicObject conditionVariable, RubyBasicObject mutex, RubyBasicObject timeout) { | ||
return waitOn(conditionVariable, mutex, new WaitAction() { | ||
@Override | ||
public void wait(Condition condition) throws InterruptedException { | ||
condition.await(); | ||
} | ||
}); | ||
} | ||
|
||
@Specialization(guards = "isRubyMutex(mutex)") | ||
RubyBasicObject wait(RubyBasicObject conditionVariable, RubyBasicObject mutex, final int timeout) { | ||
return wait(conditionVariable, mutex, (double) timeout); | ||
} | ||
|
||
@Specialization(guards = "isRubyMutex(mutex)") | ||
RubyBasicObject wait(RubyBasicObject conditionVariable, RubyBasicObject mutex, final double timeout) { | ||
final long timeoutInNanos = ((long) (timeout * 1_000_000_000)); | ||
|
||
return waitOn(conditionVariable, mutex, new WaitAction() { | ||
private long remaining = timeoutInNanos; | ||
|
||
@Override | ||
public void wait(Condition condition) throws InterruptedException { | ||
while (remaining > 0) { | ||
remaining = condition.awaitNanos(remaining); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
private RubyBasicObject waitOn(RubyBasicObject conditionVariable, RubyBasicObject mutex, final WaitAction waitAction) { | ||
final AtomicReference<RubyBasicObject> associatedMutexReference = getAssociatedMutex(conditionVariable); | ||
final AtomicReference<Condition> conditionReference = getCondition(conditionVariable); | ||
|
||
final Condition condition; | ||
if (associatedMutexReference.compareAndSet(null, mutex)) { | ||
final ReentrantLock lock = MutexNodes.getLock(mutex); | ||
condition = lock.newCondition(); | ||
conditionReference.set(condition); | ||
} else if (associatedMutexReference.get() == mutex) { | ||
condition = conditionReference.get(); | ||
} else { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().threadError("Attempt to associate a ConditionVariable which already has a Mutex", this)); | ||
} | ||
|
||
if (!MutexNodes.getLock(associatedMutexReference.get()).isHeldByCurrentThread()) { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().threadError("Called ConditionVariable#wait without holding associated Mutex", this)); | ||
} | ||
|
||
getContext().getThreadManager().runUntilResult(new BlockingActionWithoutGlobalLock<Boolean>() { | ||
@Override | ||
public Boolean block() throws InterruptedException { | ||
waitAction.wait(condition); | ||
return SUCCESS; | ||
} | ||
}); | ||
|
||
return conditionVariable; | ||
} | ||
|
||
} | ||
|
||
} |