Skip to content

Commit aa0d8b5

Browse files
committed
AST-inline Array#[]=
1 parent fbc32b6 commit aa0d8b5

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

src/main/java/org/truffleruby/core/array/ArrayNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ protected Object fallbackTernary(RubyArray array, Object start, Object length, O
430430
protected int normalize(int arraySize, int index,
431431
ConditionProfile negativeDenormalizedIndex, BranchProfile negativeNormalizedIndex) {
432432
if (negativeDenormalizedIndex.profile(index < 0)) {
433-
index = arraySize + index;
433+
index += arraySize;
434434
if (index < 0) {
435435
negativeNormalizedIndex.enter();
436436
throw new RaiseException(

src/main/java/org/truffleruby/core/inlined/CoreMethods.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public class CoreMethods {
8989
public final InternalMethod STRING_EQUAL;
9090
public final InternalMethod SYMBOL_TO_PROC;
9191
public final InternalMethod ARRAY_INDEX_GET;
92+
public final InternalMethod ARRAY_INDEX_SET;
9293

9394
public CoreMethods(RubyContext context) {
9495
this.context = context;
@@ -153,6 +154,7 @@ public CoreMethods(RubyContext context) {
153154
STRING_EQUAL = getMethod(stringClass, "==");
154155
SYMBOL_TO_PROC = getMethod(symbolClass, "to_proc");
155156
ARRAY_INDEX_GET = getMethod(arrayClass, "[]");
157+
ARRAY_INDEX_SET = getMethod(arrayClass, "[]=");
156158
}
157159

158160
private Assumption registerAssumption(RubyClass klass, String methodName) {
@@ -249,6 +251,12 @@ public RubyNode createCallNode(RubyCallNodeParameters callParameters, Translator
249251
return InlinedKindOfNodeGen.create(context, callParameters, self, args[0]);
250252
default:
251253
}
254+
} else if (n == 3) {
255+
switch (callParameters.getMethodName()) {
256+
case "[]=":
257+
return InlinedIndexSetNodeGen.create(context, callParameters, self, args[0], args[1]);
258+
default:
259+
}
252260
}
253261

254262
return new RubyCallNode(callParameters);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.core.inlined;
11+
12+
import com.oracle.truffle.api.dsl.Bind;
13+
import org.truffleruby.RubyContext;
14+
import org.truffleruby.core.array.ArrayWriteNormalizedNode;
15+
import org.truffleruby.core.array.RubyArray;
16+
import org.truffleruby.language.dispatch.RubyCallNodeParameters;
17+
import org.truffleruby.language.methods.LookupMethodOnSelfNode;
18+
19+
import com.oracle.truffle.api.dsl.Cached;
20+
import com.oracle.truffle.api.dsl.Specialization;
21+
import com.oracle.truffle.api.frame.VirtualFrame;
22+
import com.oracle.truffle.api.profiles.ConditionProfile;
23+
24+
public abstract class InlinedIndexSetNode extends TernaryInlinedOperationNode {
25+
26+
protected static final String METHOD = "[]=";
27+
28+
public InlinedIndexSetNode(RubyContext context, RubyCallNodeParameters callNodeParameters) {
29+
super(context, callNodeParameters);
30+
}
31+
32+
@Specialization(
33+
guards = {
34+
"lookupNode.lookupProtected(frame, array, METHOD) == coreMethods().ARRAY_INDEX_SET",
35+
"normalizedIndex >= 0" },
36+
assumptions = "assumptions",
37+
limit = "1")
38+
protected Object arrayWrite(VirtualFrame frame, RubyArray array, int index, Object value,
39+
@Cached LookupMethodOnSelfNode lookupNode,
40+
@Cached ConditionProfile denormalized,
41+
@Bind("normalize(array, index, denormalized)") int normalizedIndex,
42+
@Cached ArrayWriteNormalizedNode writeNode) {
43+
return writeNode.executeWrite(array, normalizedIndex, value);
44+
}
45+
46+
@Specialization
47+
protected Object fallback(VirtualFrame frame, Object a, Object b, Object c) {
48+
return rewriteAndCall(frame, a, b, c);
49+
}
50+
51+
protected int normalize(RubyArray array, int index, ConditionProfile denormalized) {
52+
if (denormalized.profile(index < 0)) {
53+
index += array.size;
54+
}
55+
return index;
56+
}
57+
58+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.core.inlined;
11+
12+
import org.truffleruby.RubyContext;
13+
import org.truffleruby.language.RubyNode;
14+
import org.truffleruby.language.dispatch.RubyCallNodeParameters;
15+
16+
import com.oracle.truffle.api.Assumption;
17+
import com.oracle.truffle.api.dsl.NodeChild;
18+
19+
@NodeChild(value = "receiver", type = RubyNode.class)
20+
@NodeChild(value = "operand1", type = RubyNode.class)
21+
@NodeChild(value = "operand2", type = RubyNode.class)
22+
public abstract class TernaryInlinedOperationNode extends InlinedOperationNode {
23+
24+
public TernaryInlinedOperationNode(
25+
RubyContext context,
26+
RubyCallNodeParameters callNodeParameters,
27+
Assumption... assumptions) {
28+
super(context, callNodeParameters, assumptions);
29+
}
30+
31+
protected abstract RubyNode getReceiver();
32+
33+
protected abstract RubyNode getOperand1();
34+
35+
protected abstract RubyNode getOperand2();
36+
37+
@Override
38+
protected RubyNode getReceiverNode() {
39+
return getReceiver();
40+
}
41+
42+
@Override
43+
protected RubyNode[] getArgumentNodes() {
44+
return new RubyNode[]{ getOperand1(), getOperand2() };
45+
}
46+
47+
}

0 commit comments

Comments
 (0)