~ubuntu-branches/ubuntu/vivid/nqp/vivid-proposed

« back to all changes in this revision

Viewing changes to src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/MultiCacheInstance.java

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2013-11-01 12:09:18 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131101120918-kx51sl0sxl3exsxi
Tags: 2013.10-1
* New upstream release
* Bump versioned (Build-)Depends on parrot
* Update patches
* Install new README.pod
* Fix vcs-field-not-canonical
* Do not install rubyish examples
* Do not Depends on parrot-devel anymore
* Add 07_disable-serialization-tests.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.perl6.nqp.sixmodel.reprs;
 
2
 
 
3
import org.perl6.nqp.runtime.CallSiteDescriptor;
 
4
import org.perl6.nqp.runtime.Ops;
 
5
import org.perl6.nqp.runtime.ThreadContext;
 
6
import org.perl6.nqp.sixmodel.SixModelObject;
 
7
import org.perl6.nqp.sixmodel.TypeObject;
 
8
 
 
9
public class MultiCacheInstance extends SixModelObject {
 
10
    private static final int MD_CACHE_MAX_ARITY = 4;
 
11
    private static final int MD_CACHE_MAX_ENTRIES = 16;
 
12
    private static final int MD_CACHE_INT = 1;
 
13
    private static final int MD_CACHE_NUM = 2;
 
14
    private static final int MD_CACHE_STR = 3;
 
15
    
 
16
    private SixModelObject zeroArity;
 
17
    private ArityCache[] arityCaches = new ArityCache[MD_CACHE_MAX_ARITY];
 
18
    
 
19
    private class ArityCache
 
20
    {
 
21
        /* The number of entries we have in the cache. */
 
22
        public int numEntries;
 
23
        
 
24
        /* This is a bunch of ST hashes, with natives special-cased. We allocate
 
25
         * it arity * MAX_ENTRIES big and go through it in arity sized chunks. */
 
26
        public long typeIds[];
 
27
        
 
28
        /* Whether the entry is allowed to have named arguments. Doesn't say
 
29
         * anything about which ones, though. Something that is ambivalent
 
30
         * about named arguments to the degree it doesn't care about them 
 
31
         * even tie-breaking (like NQP) can just throw such entries into the
 
32
         * cache. Things that do care should not make such cache entries. */
 
33
        public boolean namedOK[];
 
34
 
 
35
        /* The results we return from the cache. */
 
36
        public SixModelObject[] results;
 
37
    }
 
38
    
 
39
    public void add(CallCaptureInstance capture, SixModelObject result, ThreadContext tc) {
 
40
        /* If there's flattenings, we can't cache. */
 
41
        if (capture.descriptor.hasFlattening)
 
42
            return;
 
43
        
 
44
        /* If it's zero arity, just stick it in that slot. */
 
45
        Object[] args = capture.args;
 
46
        if (args.length == 0) {
 
47
            this.zeroArity = result;
 
48
            return;
 
49
        }
 
50
        
 
51
        /* Count number of positional args and build type tuple. */
 
52
        int numArgs = 0;
 
53
        byte[] argFlags = capture.descriptor.argFlags;
 
54
        long argTup[] = new long[MD_CACHE_MAX_ARITY];
 
55
        boolean hasNamed = false;
 
56
        for (int i = 0; i < argFlags.length; i++) {
 
57
            switch (argFlags[i]) {
 
58
            case CallSiteDescriptor.ARG_INT:
 
59
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
60
                    return;
 
61
                argTup[numArgs++] = MD_CACHE_INT;
 
62
                break;
 
63
            case CallSiteDescriptor.ARG_NUM:
 
64
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
65
                    return;
 
66
                argTup[numArgs++] = MD_CACHE_NUM;
 
67
                break;
 
68
            case CallSiteDescriptor.ARG_STR:
 
69
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
70
                    return;
 
71
                argTup[numArgs++] = MD_CACHE_STR;
 
72
                break;
 
73
            case CallSiteDescriptor.ARG_OBJ:
 
74
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
75
                    return;
 
76
                SixModelObject decont = Ops.decont((SixModelObject)args[i], tc);
 
77
                long flag = ((long)decont.st.hashCode()) << 1;
 
78
                if (!(decont instanceof TypeObject))
 
79
                    flag |= 1;
 
80
                argTup[numArgs++] = flag;
 
81
                break;
 
82
            default:
 
83
                if ((argFlags[i] & CallSiteDescriptor.ARG_FLAT) != 0)
 
84
                    return;
 
85
                hasNamed = true;
 
86
            }
 
87
        }
 
88
        
 
89
        /* If the cache is saturated, don't do anything (we could instead do a random
 
90
         * replacement). */
 
91
        ArityCache ac = this.arityCaches[numArgs - 1];
 
92
        if (ac != null && ac.numEntries == MD_CACHE_MAX_ENTRIES)
 
93
            return;
 
94
        
 
95
        /* If there's no entries yet, need to do some allocation. */
 
96
        if (ac == null) {
 
97
            ac = new ArityCache();
 
98
            ac.typeIds = new long[numArgs * MD_CACHE_MAX_ENTRIES];
 
99
            ac.namedOK = new boolean[MD_CACHE_MAX_ENTRIES];
 
100
            ac.results = new SixModelObject[MD_CACHE_MAX_ENTRIES];
 
101
            this.arityCaches[numArgs - 1] = ac;
 
102
        }
 
103
 
 
104
        /* Add entry. */
 
105
        int insType = ac.numEntries * numArgs;
 
106
        for (int i = 0; i < numArgs; i++)
 
107
            ac.typeIds[insType + i] = argTup[i];
 
108
        ac.results[ac.numEntries] = result;
 
109
        ac.namedOK[ac.numEntries] = hasNamed;
 
110
        ac.numEntries++;
 
111
    }
 
112
 
 
113
    public SixModelObject lookup(CallCaptureInstance capture, ThreadContext tc) {
 
114
        /* If there's flattenings, we can't use the cache. */
 
115
        if (capture.descriptor.hasFlattening)
 
116
            return null;
 
117
        
 
118
        /* Count number of positional args and build type tuple. */
 
119
        int numArgs = 0;
 
120
        Object[] args = capture.args;
 
121
        byte[] argFlags = capture.descriptor.argFlags;
 
122
        long argTup[] = new long[MD_CACHE_MAX_ARITY];
 
123
        boolean hasNamed = false;
 
124
        for (int i = 0; i < argFlags.length; i++) {
 
125
            switch (argFlags[i]) {
 
126
            case CallSiteDescriptor.ARG_INT:
 
127
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
128
                    return null;
 
129
                argTup[numArgs++] = MD_CACHE_INT;
 
130
                break;
 
131
            case CallSiteDescriptor.ARG_NUM:
 
132
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
133
                    return null;
 
134
                argTup[numArgs++] = MD_CACHE_NUM;
 
135
                break;
 
136
            case CallSiteDescriptor.ARG_STR:
 
137
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
138
                    return null;
 
139
                argTup[numArgs++] = MD_CACHE_STR;
 
140
                break;
 
141
            case CallSiteDescriptor.ARG_OBJ:
 
142
                if (numArgs >= MD_CACHE_MAX_ARITY)
 
143
                    return null;
 
144
                SixModelObject decont = Ops.decont((SixModelObject)args[i], tc);
 
145
                long flag = ((long)decont.st.hashCode()) << 1;
 
146
                if (!(decont instanceof TypeObject))
 
147
                    flag |= 1;
 
148
                argTup[numArgs++] = flag;
 
149
                break;
 
150
            default:
 
151
                if ((argFlags[i] & CallSiteDescriptor.ARG_FLAT) != 0)
 
152
                    return null;
 
153
                hasNamed = true;
 
154
            }
 
155
        }
 
156
        
 
157
        /* If it's zero-arity, return result right off. */
 
158
        if (numArgs == 0)
 
159
            return hasNamed ? null : this.zeroArity;
 
160
 
 
161
        /* Look through entries. */
 
162
        ArityCache ac = this.arityCaches[numArgs - 1];
 
163
        if (ac == null)
 
164
            return null;
 
165
        int tPos = 0;
 
166
        for (int i = 0; i < ac.numEntries; i++) {
 
167
            boolean match = true;
 
168
            for (int j = 0; j < numArgs; j++) {
 
169
                if (ac.typeIds[tPos + j] != argTup[j]) {
 
170
                    match = false;
 
171
                    break;
 
172
                }
 
173
            }
 
174
            if (match) {
 
175
                if (hasNamed == ac.namedOK[i])
 
176
                    return ac.results[i];
 
177
            }
 
178
            tPos += numArgs;
 
179
        }
 
180
 
 
181
        return null;
 
182
    }
 
183
}