001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2007 Ye Zheng <dreamhead.cn@gmail.com>
015: *
016: * Alternatively, the contents of this file may be used under the terms of
017: * either of the GNU General Public License Version 2 or later (the "GPL"),
018: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
019: * in which case the provisions of the GPL or the LGPL are applicable instead
020: * of those above. If you wish to allow use of your version of this file only
021: * under the terms of either the GPL or the LGPL, and not to allow others to
022: * use your version of this file under the terms of the CPL, indicate your
023: * decision by deleting the provisions above and replace them with the notice
024: * and other provisions required by the GPL or the LGPL. If you do not delete
025: * the provisions above, a recipient may use your version of this file under
026: * the terms of any one of the CPL, the GPL or the LGPL.
027: ***** END LICENSE BLOCK *****/package org.jruby.util;
028:
029: import org.jruby.RubyClass;
030: import org.jruby.RubyModule;
031: import org.jruby.internal.runtime.methods.DynamicMethod;
032:
033: public class MethodCache {
034: private static int CACHE_SIZE = 0x800;
035: private static int CACHE_MASK = 0x7ff;
036:
037: private boolean initialized;
038:
039: private CacheEntry[] cache;
040:
041: public MethodCache() {
042: initialized = false;
043:
044: cache = new CacheEntry[CACHE_SIZE];
045: clearAllEntries();
046: }
047:
048: public void initialized() {
049: initialized = true;
050: }
051:
052: public void clearCache() {
053: if (!initialized) {
054: return;
055: }
056:
057: clearAllEntries();
058: }
059:
060: private void clearAllEntries() {
061: for (int i = 0; i < CACHE_SIZE; i++) {
062: cache[i] = new CacheEntry();
063: cache[i].klass = null;
064: cache[i].mid = null;
065: cache[i].method = null;
066: }
067: }
068:
069: private int cacheIndex(RubyModule c, String id) {
070: return (((c.hashCode() >> 3) ^ (id.hashCode())) & CACHE_MASK);
071: }
072:
073: public CacheEntry getMethod(RubyModule c, String id) {
074: int index = cacheIndex(c, id);
075: return cache[index];
076: }
077:
078: public void putMethod(RubyModule c, String id, DynamicMethod m) {
079: int index = cacheIndex(c, id);
080:
081: cache[index].klass = c;
082: cache[index].mid = id;
083: cache[index].method = m;
084: }
085:
086: public void removeMethod(RubyClass c, String id) {
087: if (!initialized) {
088: return;
089: }
090:
091: for (int i = 0; i < CACHE_SIZE; i++) {
092: CacheEntry entry = cache[i];
093: if (id.equals(entry.mid) && entry.klass == c) {
094: entry.mid = null;
095: }
096: }
097: }
098:
099: public void removeMethod(String id) {
100: if (!initialized) {
101: return;
102: }
103:
104: for (int i = 0; i < CACHE_SIZE; i++) {
105: CacheEntry entry = cache[i];
106: if (id.equals(entry.mid)) {
107: entry.mid = null;
108: }
109: }
110: }
111:
112: public void removeClass(RubyClass c) {
113: if (!initialized) {
114: return;
115: }
116:
117: for (int i = 0; i < CACHE_SIZE; i++) {
118: CacheEntry entry = cache[i];
119: if (entry.klass == c) {
120: entry.mid = null;
121: }
122: }
123: }
124:
125: public static class CacheEntry {
126: public RubyModule klass;
127: public String mid;
128: public DynamicMethod method;
129: }
130: }
|