1
0
Nicolas Petton 12 лет назад
Родитель
Сommit
70d1319009

+ 335 - 17
js/Helios-Browser.deploy.js

@@ -611,7 +611,7 @@ smalltalk.HLClassesListWidget);
 
 
 
-smalltalk.addClass('HLMethodsListWidget', smalltalk.HLBrowserListWidget, ['selectorsCache'], 'Helios-Browser');
+smalltalk.addClass('HLMethodsListWidget', smalltalk.HLBrowserListWidget, [], 'Helios-Browser');
 smalltalk.addMethod(
 "_allProtocol",
 smalltalk.method({
@@ -645,7 +645,7 @@ var self=this;
 var override,overriden;
 return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
 override=_st(self)._isOverride_(aCompiledMethod);
-overriden=_st(self)._isOverriden_(aCompiledMethod);
+overriden=_st(self)._isOverridden_(aCompiledMethod);
 $2=override;
 if(smalltalk.assert($2)){
 $3=overriden;
@@ -664,7 +664,7 @@ $1="icon-none";
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"iconForItem:",{aCompiledMethod:aCompiledMethod,override:override,overriden:overriden}, smalltalk.HLMethodsListWidget)})},
-messageSends: ["isOverride:", "isOverriden:", "ifTrue:ifFalse:"]}),
+messageSends: ["isOverride:", "isOverridden:", "ifTrue:ifFalse:"]}),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
@@ -680,29 +680,29 @@ messageSends: ["initialize", "flushSelectorsCache"]}),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
-"_isOverride_",
+"_isOverridden_",
 smalltalk.method({
-selector: "isOverride:",
+selector: "isOverridden:",
 fn: function (aMethod){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._overrideSelectors())._includes_(_st(aMethod)._selector());
+$1=_st(_st(self)._selectorsCache())._isOverridden_(aMethod);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
-messageSends: ["includes:", "selector", "overrideSelectors"]}),
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
+messageSends: ["isOverridden:", "selectorsCache"]}),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
-"_isOverriden_",
+"_isOverride_",
 smalltalk.method({
-selector: "isOverriden:",
+selector: "isOverride:",
 fn: function (aMethod){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._overridenSelectors())._includes_(_st(aMethod)._selector());
+$1=_st(_st(self)._selectorsCache())._isOverride_(aMethod);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isOverriden:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
-messageSends: ["includes:", "selector", "overridenSelectors"]}),
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
+messageSends: ["isOverride:", "selectorsCache"]}),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
@@ -846,9 +846,8 @@ return smalltalk.withContext(function($ctx2) {
return smalltalk.HLBrowserListWid
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 $3;
 };
-_st(self)._flushSelectorsCache();
 return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html}, smalltalk.HLMethodsListWidget)})},
-messageSends: ["ifFalse:ifTrue:", "class:", "div", "with:", "renderContentOn:", "showInstance", "model", "flushSelectorsCache"]}),
+messageSends: ["ifFalse:ifTrue:", "class:", "div", "with:", "renderContentOn:", "showInstance", "model"]}),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
@@ -880,13 +879,27 @@ selector: "selectorsCache",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@selectorsCache"];
+$1=_st(_st(self)._class())._selectorsCache();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"selectorsCache",{}, smalltalk.HLMethodsListWidget)})},
-messageSends: []}),
+messageSends: ["selectorsCache", "class"]}),
 smalltalk.HLMethodsListWidget);
 
 
+smalltalk.HLMethodsListWidget.klass.iVarNames = ['selectorsCache'];
+smalltalk.addMethod(
+"_selectorsCache",
+smalltalk.method({
+selector: "selectorsCache",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLSelectorsCache || HLSelectorsCache))._current();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectorsCache",{}, smalltalk.HLMethodsListWidget.klass)})},
+messageSends: ["current"]}),
+smalltalk.HLMethodsListWidget.klass);
+
 
 smalltalk.addClass('HLPackagesListWidget', smalltalk.HLBrowserListWidget, [], 'Helios-Browser');
 smalltalk.addMethod(
@@ -1610,3 +1623,308 @@ messageSends: ["model:", "new", "yourself"]}),
 smalltalk.HLBrowserSourceWidget.klass);
 
 
+smalltalk.addClass('HLClassCache', smalltalk.Object, ['class', 'parentCache', 'overrideCache', 'overriddenCache'], 'Helios-Browser');
+smalltalk.addMethod(
+"_isOverridden_",
+smalltalk.method({
+selector: "isOverridden:",
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._overriddenCache())._at_ifAbsentPut_(_st(aMethod)._selector(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(aMethod)._isOverridden();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLClassCache)})},
+messageSends: ["at:ifAbsentPut:", "selector", "isOverridden", "overriddenCache"]}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_isOverride_",
+smalltalk.method({
+selector: "isOverride:",
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._overrideCache())._at_ifAbsentPut_(_st(aMethod)._selector(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(aMethod)._isOverride();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLClassCache)})},
+messageSends: ["at:ifAbsentPut:", "selector", "isOverride", "overrideCache"]}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_overriddenCache",
+smalltalk.method({
+selector: "overriddenCache",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@overriddenCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@overriddenCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@overriddenCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"overriddenCache",{}, smalltalk.HLClassCache)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_overrideCache",
+smalltalk.method({
+selector: "overrideCache",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@overrideCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@overrideCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@overrideCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"overrideCache",{}, smalltalk.HLClassCache)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_parentCache",
+smalltalk.method({
+selector: "parentCache",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@parentCache"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"parentCache",{}, smalltalk.HLClassCache)})},
+messageSends: []}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_parentCache_",
+smalltalk.method({
+selector: "parentCache:",
+fn: function (aCache){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@parentCache"]=aCache;
+return self}, function($ctx1) {$ctx1.fill(self,"parentCache:",{aCache:aCache}, smalltalk.HLClassCache)})},
+messageSends: []}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_theClass",
+smalltalk.method({
+selector: "theClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@class"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"theClass",{}, smalltalk.HLClassCache)})},
+messageSends: []}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_theClass_",
+smalltalk.method({
+selector: "theClass:",
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@class"]=aClass;
+return self}, function($ctx1) {$ctx1.fill(self,"theClass:",{aClass:aClass}, smalltalk.HLClassCache)})},
+messageSends: []}),
+smalltalk.HLClassCache);
+
+
+smalltalk.addMethod(
+"_on_parentCache_",
+smalltalk.method({
+selector: "on:parentCache:",
+fn: function (aClass,aCache){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._theClass_(aClass);
+_st($2)._parentCache_(aCache);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:parentCache:",{aClass:aClass,aCache:aCache}, smalltalk.HLClassCache.klass)})},
+messageSends: ["theClass:", "new", "parentCache:", "yourself"]}),
+smalltalk.HLClassCache.klass);
+
+
+smalltalk.addClass('HLSelectorsCache', smalltalk.Object, ['classesCache'], 'Helios-Browser');
+smalltalk.addMethod(
+"_cacheFor_",
+smalltalk.method({
+selector: "cacheFor:",
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=aClass;
+if(($receiver = $1) == nil || $receiver == undefined){
+return nil;
+} else {
+$1;
+};
+$2=_st(_st(self)._classesCache())._at_ifAbsentPut_(_st(aClass)._name(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._newCacheFor_(aClass);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"cacheFor:",{aClass:aClass}, smalltalk.HLSelectorsCache)})},
+messageSends: ["ifNil:", "at:ifAbsentPut:", "name", "newCacheFor:", "classesCache"]}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_classesCache",
+smalltalk.method({
+selector: "classesCache",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@classesCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@classesCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@classesCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"classesCache",{}, smalltalk.HLSelectorsCache)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_isOverridden_",
+smalltalk.method({
+selector: "isOverridden:",
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._cacheFor_(_st(aMethod)._methodClass()))._isOverridden_(aMethod);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLSelectorsCache)})},
+messageSends: ["isOverridden:", "cacheFor:", "methodClass"]}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_isOverride_",
+smalltalk.method({
+selector: "isOverride:",
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._cacheFor_(_st(aMethod)._methodClass()))._isOverride_(aMethod);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLSelectorsCache)})},
+messageSends: ["isOverride:", "cacheFor:", "methodClass"]}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_newCacheFor_",
+smalltalk.method({
+selector: "newCacheFor:",
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLClassCache || HLClassCache))._on_parentCache_(aClass,_st(self)._cacheFor_(_st(aClass)._superclass()));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCacheFor:",{aClass:aClass}, smalltalk.HLSelectorsCache)})},
+messageSends: ["on:parentCache:", "cacheFor:", "superclass"]}),
+smalltalk.HLSelectorsCache);
+
+
+smalltalk.HLSelectorsCache.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+"_current",
+smalltalk.method({
+selector: "current",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@current"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@current"]=smalltalk.Object.klass.fn.prototype._new.apply(_st(self), []);
+$1=self["@current"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"current",{}, smalltalk.HLSelectorsCache.klass)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLSelectorsCache.klass);
+
+smalltalk.addMethod(
+"_flush",
+smalltalk.method({
+selector: "flush",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@current"]=nil;
+return self}, function($ctx1) {$ctx1.fill(self,"flush",{}, smalltalk.HLSelectorsCache.klass)})},
+messageSends: []}),
+smalltalk.HLSelectorsCache.klass);
+
+smalltalk.addMethod(
+"_new",
+smalltalk.method({
+selector: "new",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._shouldNotImplement();
+return self}, function($ctx1) {$ctx1.fill(self,"new",{}, smalltalk.HLSelectorsCache.klass)})},
+messageSends: ["shouldNotImplement"]}),
+smalltalk.HLSelectorsCache.klass);
+
+
+smalltalk.addMethod(
+"_isOverridden",
+smalltalk.method({
+selector: "isOverridden",
+fn: function (){
+var self=this;
+var selector;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+var $early={};
+try {
+selector=_st(self)._selector();
+_st(_st(self)._methodClass())._allSubclassesDo_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._includesSelector_(selector);
+if(smalltalk.assert($1)){
+throw $early=[true];
+};
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return false;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"isOverridden",{selector:selector}, smalltalk.CompiledMethod)})},
+messageSends: ["selector", "allSubclassesDo:", "ifTrue:", "includesSelector:", "methodClass"]}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_isOverride",
+smalltalk.method({
+selector: "isOverride",
+fn: function (){
+var self=this;
+var superclass;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+superclass=_st(_st(self)._methodClass())._superclass();
+$1=superclass;
+if(($receiver = $1) == nil || $receiver == undefined){
+return false;
+} else {
+$1;
+};
+$2=_st(_st(_st(_st(self)._methodClass())._superclass())._lookupSelector_(_st(self)._selector()))._isNil();
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"isOverride",{superclass:superclass}, smalltalk.CompiledMethod)})},
+messageSends: ["superclass", "methodClass", "ifNil:", "isNil", "lookupSelector:", "selector"]}),
+smalltalk.CompiledMethod);
+

+ 440 - 22
js/Helios-Browser.js

@@ -796,7 +796,7 @@ smalltalk.HLClassesListWidget);
 
 
 
-smalltalk.addClass('HLMethodsListWidget', smalltalk.HLBrowserListWidget, ['selectorsCache'], 'Helios-Browser');
+smalltalk.addClass('HLMethodsListWidget', smalltalk.HLBrowserListWidget, [], 'Helios-Browser');
 smalltalk.addMethod(
 "_allProtocol",
 smalltalk.method({
@@ -841,7 +841,7 @@ var self=this;
 var override,overriden;
 return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
 override=_st(self)._isOverride_(aCompiledMethod);
-overriden=_st(self)._isOverriden_(aCompiledMethod);
+overriden=_st(self)._isOverridden_(aCompiledMethod);
 $2=override;
 if(smalltalk.assert($2)){
 $3=overriden;
@@ -861,8 +861,8 @@ $1="icon-none";
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"iconForItem:",{aCompiledMethod:aCompiledMethod,override:override,overriden:overriden}, smalltalk.HLMethodsListWidget)})},
 args: ["aCompiledMethod"],
-source: "iconForItem: aCompiledMethod\x0a\x09| override overriden |\x0a    \x0a    override := self isOverride: aCompiledMethod.\x0a    overriden := self isOverriden: aCompiledMethod.\x0a    \x0a\x09^ override\x0a    \x09ifTrue: [ overriden\x0a\x09\x09\x09ifTrue: [ 'icon-resize-vertical' ]\x0a\x09\x09\x09ifFalse: [ 'icon-arrow-up' ] ]\x0a\x09\x09ifFalse: [\x0a\x09\x09\x09overriden\x0a\x09\x09\x09ifTrue: [ 'icon-arrow-down' ]\x0a\x09\x09\x09ifFalse: [ 'icon-none' ] ]",
-messageSends: ["isOverride:", "isOverriden:", "ifTrue:ifFalse:"],
+source: "iconForItem: aCompiledMethod\x0a\x09| override overriden |\x0a    \x0a    override := self isOverride: aCompiledMethod.\x0a    overriden := self isOverridden: aCompiledMethod.\x0a    \x0a\x09^ override\x0a    \x09ifTrue: [ overriden\x0a\x09\x09\x09ifTrue: [ 'icon-resize-vertical' ]\x0a\x09\x09\x09ifFalse: [ 'icon-arrow-up' ] ]\x0a\x09\x09ifFalse: [\x0a\x09\x09\x09overriden\x0a\x09\x09\x09ifTrue: [ 'icon-arrow-down' ]\x0a\x09\x09\x09ifFalse: [ 'icon-none' ] ]",
+messageSends: ["isOverride:", "isOverridden:", "ifTrue:ifFalse:"],
 referencedClasses: []
 }),
 smalltalk.HLMethodsListWidget);
@@ -885,37 +885,37 @@ referencedClasses: []
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
-"_isOverride_",
+"_isOverridden_",
 smalltalk.method({
-selector: "isOverride:",
+selector: "isOverridden:",
 category: 'testing',
 fn: function (aMethod){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._overrideSelectors())._includes_(_st(aMethod)._selector());
+$1=_st(_st(self)._selectorsCache())._isOverridden_(aMethod);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
 args: ["aMethod"],
-source: "isOverride: aMethod\x0a\x0a   ^ self overrideSelectors includes: aMethod selector",
-messageSends: ["includes:", "selector", "overrideSelectors"],
+source: "isOverridden: aMethod\x0a   ^ self selectorsCache isOverridden: aMethod",
+messageSends: ["isOverridden:", "selectorsCache"],
 referencedClasses: []
 }),
 smalltalk.HLMethodsListWidget);
 
 smalltalk.addMethod(
-"_isOverriden_",
+"_isOverride_",
 smalltalk.method({
-selector: "isOverriden:",
+selector: "isOverride:",
 category: 'testing',
 fn: function (aMethod){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._overridenSelectors())._includes_(_st(aMethod)._selector());
+$1=_st(_st(self)._selectorsCache())._isOverride_(aMethod);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isOverriden:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLMethodsListWidget)})},
 args: ["aMethod"],
-source: "isOverriden: aMethod\x0a\x0a   ^ self overridenSelectors includes: aMethod selector",
-messageSends: ["includes:", "selector", "overridenSelectors"],
+source: "isOverride: aMethod\x0a   ^ self selectorsCache isOverride: aMethod",
+messageSends: ["isOverride:", "selectorsCache"],
 referencedClasses: []
 }),
 smalltalk.HLMethodsListWidget);
@@ -1092,11 +1092,10 @@ return smalltalk.withContext(function($ctx2) {
return smalltalk.HLBrowserListWid
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 $3;
 };
-_st(self)._flushSelectorsCache();
 return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html}, smalltalk.HLMethodsListWidget)})},
 args: ["html"],
-source: "renderContentOn: html\x0a\x09self model showInstance\x0a    \x09ifFalse: [ html div \x0a        \x09class: 'class_side'; \x0a            with: [ super renderContentOn: html ] ]\x0a      \x09ifTrue: [ super renderContentOn: html ].\x0a        \x0a    self flushSelectorsCache",
-messageSends: ["ifFalse:ifTrue:", "class:", "div", "with:", "renderContentOn:", "showInstance", "model", "flushSelectorsCache"],
+source: "renderContentOn: html\x0a\x09self model showInstance\x0a    \x09ifFalse: [ html div \x0a        \x09class: 'class_side'; \x0a            with: [ super renderContentOn: html ] ]\x0a      \x09ifTrue: [ super renderContentOn: html ].\x0a        \x0a    \x22self flushSelectorsCache\x22",
+messageSends: ["ifFalse:ifTrue:", "class:", "div", "with:", "renderContentOn:", "showInstance", "model"],
 referencedClasses: []
 }),
 smalltalk.HLMethodsListWidget);
@@ -1141,17 +1140,36 @@ category: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@selectorsCache"];
+$1=_st(_st(self)._class())._selectorsCache();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"selectorsCache",{}, smalltalk.HLMethodsListWidget)})},
 args: [],
-source: "selectorsCache\x0a\x09^ selectorsCache",
-messageSends: [],
+source: "selectorsCache\x0a\x09^ self class selectorsCache",
+messageSends: ["selectorsCache", "class"],
 referencedClasses: []
 }),
 smalltalk.HLMethodsListWidget);
 
 
+smalltalk.HLMethodsListWidget.klass.iVarNames = ['selectorsCache'];
+smalltalk.addMethod(
+"_selectorsCache",
+smalltalk.method({
+selector: "selectorsCache",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLSelectorsCache || HLSelectorsCache))._current();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectorsCache",{}, smalltalk.HLMethodsListWidget.klass)})},
+args: [],
+source: "selectorsCache\x0a\x09^ HLSelectorsCache current",
+messageSends: ["current"],
+referencedClasses: ["HLSelectorsCache"]
+}),
+smalltalk.HLMethodsListWidget.klass);
+
 
 smalltalk.addClass('HLPackagesListWidget', smalltalk.HLBrowserListWidget, [], 'Helios-Browser');
 smalltalk.addMethod(
@@ -2090,3 +2108,403 @@ referencedClasses: []
 smalltalk.HLBrowserSourceWidget.klass);
 
 
+smalltalk.addClass('HLClassCache', smalltalk.Object, ['class', 'parentCache', 'overrideCache', 'overriddenCache'], 'Helios-Browser');
+smalltalk.addMethod(
+"_isOverridden_",
+smalltalk.method({
+selector: "isOverridden:",
+category: 'testing',
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._overriddenCache())._at_ifAbsentPut_(_st(aMethod)._selector(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(aMethod)._isOverridden();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLClassCache)})},
+args: ["aMethod"],
+source: "isOverridden: aMethod\x0a\x09^ self overriddenCache \x0a    \x09at: aMethod selector\x0a      \x09ifAbsentPut: [ aMethod isOverridden ]",
+messageSends: ["at:ifAbsentPut:", "selector", "isOverridden", "overriddenCache"],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_isOverride_",
+smalltalk.method({
+selector: "isOverride:",
+category: 'testing',
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._overrideCache())._at_ifAbsentPut_(_st(aMethod)._selector(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(aMethod)._isOverride();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLClassCache)})},
+args: ["aMethod"],
+source: "isOverride: aMethod\x0a\x09^ self overrideCache\x0a    \x09at: aMethod selector\x0a      \x09ifAbsentPut: [ aMethod isOverride ]",
+messageSends: ["at:ifAbsentPut:", "selector", "isOverride", "overrideCache"],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_overriddenCache",
+smalltalk.method({
+selector: "overriddenCache",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@overriddenCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@overriddenCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@overriddenCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"overriddenCache",{}, smalltalk.HLClassCache)})},
+args: [],
+source: "overriddenCache\x0a\x09^ overriddenCache ifNil: [ overriddenCache := HashedCollection new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["HashedCollection"]
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_overrideCache",
+smalltalk.method({
+selector: "overrideCache",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@overrideCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@overrideCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@overrideCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"overrideCache",{}, smalltalk.HLClassCache)})},
+args: [],
+source: "overrideCache\x0a\x09^ overrideCache ifNil: [ overrideCache := HashedCollection new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["HashedCollection"]
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_parentCache",
+smalltalk.method({
+selector: "parentCache",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@parentCache"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"parentCache",{}, smalltalk.HLClassCache)})},
+args: [],
+source: "parentCache\x0a\x09^ parentCache",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_parentCache_",
+smalltalk.method({
+selector: "parentCache:",
+category: 'accessing',
+fn: function (aCache){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@parentCache"]=aCache;
+return self}, function($ctx1) {$ctx1.fill(self,"parentCache:",{aCache:aCache}, smalltalk.HLClassCache)})},
+args: ["aCache"],
+source: "parentCache: aCache\x0a\x09parentCache := aCache",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_theClass",
+smalltalk.method({
+selector: "theClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@class"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"theClass",{}, smalltalk.HLClassCache)})},
+args: [],
+source: "theClass\x0a\x09^ class",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+smalltalk.addMethod(
+"_theClass_",
+smalltalk.method({
+selector: "theClass:",
+category: 'accessing',
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@class"]=aClass;
+return self}, function($ctx1) {$ctx1.fill(self,"theClass:",{aClass:aClass}, smalltalk.HLClassCache)})},
+args: ["aClass"],
+source: "theClass: aClass\x0a\x09class := aClass",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLClassCache);
+
+
+smalltalk.addMethod(
+"_on_parentCache_",
+smalltalk.method({
+selector: "on:parentCache:",
+category: 'instance creation',
+fn: function (aClass,aCache){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._theClass_(aClass);
+_st($2)._parentCache_(aCache);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:parentCache:",{aClass:aClass,aCache:aCache}, smalltalk.HLClassCache.klass)})},
+args: ["aClass", "aCache"],
+source: "on: aClass parentCache: aCache\x0a\x09^ self new\x0a    \x09theClass: aClass;\x0a        parentCache: aCache;\x0a        yourself",
+messageSends: ["theClass:", "new", "parentCache:", "yourself"],
+referencedClasses: []
+}),
+smalltalk.HLClassCache.klass);
+
+
+smalltalk.addClass('HLSelectorsCache', smalltalk.Object, ['classesCache'], 'Helios-Browser');
+smalltalk.addMethod(
+"_cacheFor_",
+smalltalk.method({
+selector: "cacheFor:",
+category: 'accessing',
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=aClass;
+if(($receiver = $1) == nil || $receiver == undefined){
+return nil;
+} else {
+$1;
+};
+$2=_st(_st(self)._classesCache())._at_ifAbsentPut_(_st(aClass)._name(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._newCacheFor_(aClass);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"cacheFor:",{aClass:aClass}, smalltalk.HLSelectorsCache)})},
+args: ["aClass"],
+source: "cacheFor: aClass\x0a\x09aClass ifNil: [ ^ nil ].\x0a    \x0a\x09^ self classesCache\x0a    \x09at: aClass name\x0a        ifAbsentPut: [ self newCacheFor: aClass ]",
+messageSends: ["ifNil:", "at:ifAbsentPut:", "name", "newCacheFor:", "classesCache"],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_classesCache",
+smalltalk.method({
+selector: "classesCache",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@classesCache"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@classesCache"]=_st((smalltalk.HashedCollection || HashedCollection))._new();
+$1=self["@classesCache"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"classesCache",{}, smalltalk.HLSelectorsCache)})},
+args: [],
+source: "classesCache\x0a\x09^ classesCache ifNil: [ classesCache := HashedCollection new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["HashedCollection"]
+}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_isOverridden_",
+smalltalk.method({
+selector: "isOverridden:",
+category: 'testing',
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._cacheFor_(_st(aMethod)._methodClass()))._isOverridden_(aMethod);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverridden:",{aMethod:aMethod}, smalltalk.HLSelectorsCache)})},
+args: ["aMethod"],
+source: "isOverridden: aMethod\x0a\x09^ (self cacheFor: aMethod methodClass)\x0a    \x09isOverridden: aMethod",
+messageSends: ["isOverridden:", "cacheFor:", "methodClass"],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_isOverride_",
+smalltalk.method({
+selector: "isOverride:",
+category: 'testing',
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._cacheFor_(_st(aMethod)._methodClass()))._isOverride_(aMethod);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isOverride:",{aMethod:aMethod}, smalltalk.HLSelectorsCache)})},
+args: ["aMethod"],
+source: "isOverride: aMethod\x0a\x09^ (self cacheFor: aMethod methodClass)\x0a    \x09isOverride: aMethod",
+messageSends: ["isOverride:", "cacheFor:", "methodClass"],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache);
+
+smalltalk.addMethod(
+"_newCacheFor_",
+smalltalk.method({
+selector: "newCacheFor:",
+category: 'factory',
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLClassCache || HLClassCache))._on_parentCache_(aClass,_st(self)._cacheFor_(_st(aClass)._superclass()));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCacheFor:",{aClass:aClass}, smalltalk.HLSelectorsCache)})},
+args: ["aClass"],
+source: "newCacheFor: aClass\x0a\x09^ HLClassCache \x0a    \x09on: aClass\x0a        parentCache: (self cacheFor: aClass superclass)",
+messageSends: ["on:parentCache:", "cacheFor:", "superclass"],
+referencedClasses: ["HLClassCache"]
+}),
+smalltalk.HLSelectorsCache);
+
+
+smalltalk.HLSelectorsCache.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+"_current",
+smalltalk.method({
+selector: "current",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@current"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@current"]=smalltalk.Object.klass.fn.prototype._new.apply(_st(self), []);
+$1=self["@current"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"current",{}, smalltalk.HLSelectorsCache.klass)})},
+args: [],
+source: "current\x0a\x09^ current ifNil: [ current := super new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache.klass);
+
+smalltalk.addMethod(
+"_flush",
+smalltalk.method({
+selector: "flush",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@current"]=nil;
+return self}, function($ctx1) {$ctx1.fill(self,"flush",{}, smalltalk.HLSelectorsCache.klass)})},
+args: [],
+source: "flush\x0a\x09current := nil",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache.klass);
+
+smalltalk.addMethod(
+"_new",
+smalltalk.method({
+selector: "new",
+category: 'instance creation',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._shouldNotImplement();
+return self}, function($ctx1) {$ctx1.fill(self,"new",{}, smalltalk.HLSelectorsCache.klass)})},
+args: [],
+source: "new\x0a\x09self shouldNotImplement",
+messageSends: ["shouldNotImplement"],
+referencedClasses: []
+}),
+smalltalk.HLSelectorsCache.klass);
+
+
+smalltalk.addMethod(
+"_isOverridden",
+smalltalk.method({
+selector: "isOverridden",
+category: '*Helios-Browser',
+fn: function (){
+var self=this;
+var selector;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+var $early={};
+try {
+selector=_st(self)._selector();
+_st(_st(self)._methodClass())._allSubclassesDo_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._includesSelector_(selector);
+if(smalltalk.assert($1)){
+throw $early=[true];
+};
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return false;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"isOverridden",{selector:selector}, smalltalk.CompiledMethod)})},
+args: [],
+source: "isOverridden\x0a\x09| selector |\x0a    \x0a    selector := self selector.\x0a    self methodClass allSubclassesDo: [ :each |\x0a\x09    (each includesSelector: selector)\x0a        \x09ifTrue: [ ^ true ] ].\x0a\x09^ false",
+messageSends: ["selector", "allSubclassesDo:", "ifTrue:", "includesSelector:", "methodClass"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_isOverride",
+smalltalk.method({
+selector: "isOverride",
+category: '*Helios-Browser',
+fn: function (){
+var self=this;
+var superclass;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+superclass=_st(_st(self)._methodClass())._superclass();
+$1=superclass;
+if(($receiver = $1) == nil || $receiver == undefined){
+return false;
+} else {
+$1;
+};
+$2=_st(_st(_st(_st(self)._methodClass())._superclass())._lookupSelector_(_st(self)._selector()))._isNil();
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"isOverride",{superclass:superclass}, smalltalk.CompiledMethod)})},
+args: [],
+source: "isOverride\x0a\x09| superclass |\x0a    \x0a    superclass := self methodClass superclass.\x0a\x09superclass ifNil: [ ^ false ].\x0a\x09\x0a    ^ (self methodClass superclass lookupSelector: self selector) isNil",
+messageSends: ["superclass", "methodClass", "ifNil:", "isNil", "lookupSelector:", "selector"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+

+ 15 - 1
js/Kernel-Classes.deploy.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Classes', {});
+smalltalk.addPackage('Kernel-Classes');
 smalltalk.addClass('Behavior', smalltalk.Object, [], 'Kernel-Classes');
 smalltalk.addMethod(
 "_addCompiledMethod_",
@@ -56,6 +56,20 @@ return $1;
 messageSends: ["subclasses", "do:", "addAll:", "allSubclasses"]}),
 smalltalk.Behavior);
 
+smalltalk.addMethod(
+"_allSubclassesDo_",
+smalltalk.method({
+selector: "allSubclassesDo:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._subclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
_st(aBlock)._value_(each);
+return _st(each)._allSubclassesDo_(aBlock);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"allSubclassesDo:",{aBlock:aBlock}, smalltalk.Behavior)})},
+messageSends: ["do:", "value:", "allSubclassesDo:", "subclasses"]}),
+smalltalk.Behavior);
+
 smalltalk.addMethod(
 "_allSuperclasses",
 smalltalk.method({

+ 21 - 2
js/Kernel-Classes.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Classes', {});
+smalltalk.addPackage('Kernel-Classes');
 smalltalk.addClass('Behavior', smalltalk.Object, [], 'Kernel-Classes');
 smalltalk.Behavior.comment="Behavior is the superclass of all class objects. \x0a\x0aIt defines the protocol for creating instances of a class with `#basicNew` and `#new` (see `boot.js` for class constructors details).\x0aInstances know about the subclass/superclass relationships between classes, contain the description that instances are created from, \x0aand hold the method dictionary that's associated with each class.\x0a\x0aBehavior also  provides methods for compiling methods, examining the method dictionary, and iterating over the class hierarchy."
 smalltalk.addMethod(
@@ -72,6 +72,25 @@ referencedClasses: []
 }),
 smalltalk.Behavior);
 
+smalltalk.addMethod(
+"_allSubclassesDo_",
+smalltalk.method({
+selector: "allSubclassesDo:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._subclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
_st(aBlock)._value_(each);
+return _st(each)._allSubclassesDo_(aBlock);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"allSubclassesDo:",{aBlock:aBlock}, smalltalk.Behavior)})},
+args: ["aBlock"],
+source: "allSubclassesDo: aBlock\x0a\x09\x22Evaluate the argument, aBlock, for each of the receiver's subclasses.\x22\x0a\x0a\x09self subclasses do: [ :each |\x0a    \x09aBlock value: each.\x0a        each allSubclassesDo: aBlock ].",
+messageSends: ["do:", "value:", "allSubclassesDo:", "subclasses"],
+referencedClasses: []
+}),
+smalltalk.Behavior);
+
 smalltalk.addMethod(
 "_allSuperclasses",
 smalltalk.method({
@@ -581,7 +600,7 @@ smalltalk.addMethod(
 "_protocolsDo_",
 smalltalk.method({
 selector: "protocolsDo:",
-category: 'accessing',
+category: 'enumerating',
 fn: function (aBlock){
 var self=this;
 var methodsByCategory;

+ 1 - 1
js/Kernel-Methods.deploy.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Methods', {});
+smalltalk.addPackage('Kernel-Methods');
 smalltalk.addClass('BlockClosure', smalltalk.Object, [], 'Kernel-Methods');
 smalltalk.addMethod(
 "_applyTo_arguments_",

+ 1 - 1
js/Kernel-Methods.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Methods', {});
+smalltalk.addPackage('Kernel-Methods');
 smalltalk.addClass('BlockClosure', smalltalk.Object, [], 'Kernel-Methods');
 smalltalk.BlockClosure.comment="A BlockClosure is a lexical closure.\x0aThe JavaScript representation is a function.\x0a\x0aA BlockClosure is evaluated with the `#value*` methods in the 'evaluating' protocol."
 smalltalk.addMethod(

+ 144 - 8
st/Helios-Browser.st

@@ -275,7 +275,7 @@ renderListOn: html
 ! !
 
 HLBrowserListWidget subclass: #HLMethodsListWidget
-	instanceVariableNames: 'selectorsCache'
+	instanceVariableNames: ''
 	package: 'Helios-Browser'!
 
 !HLMethodsListWidget methodsFor: 'accessing'!
@@ -288,7 +288,7 @@ iconForItem: aCompiledMethod
 	| override overriden |
     
     override := self isOverride: aCompiledMethod.
-    overriden := self isOverriden: aCompiledMethod.
+    overriden := self isOverridden: aCompiledMethod.
     
 	^ override
     	ifTrue: [ overriden
@@ -323,7 +323,7 @@ overridenSelectors
 !
 
 selectorsCache
-	^ selectorsCache
+	^ self class selectorsCache
 ! !
 
 !HLMethodsListWidget methodsFor: 'actions'!
@@ -384,7 +384,7 @@ renderContentOn: html
             with: [ super renderContentOn: html ] ]
       	ifTrue: [ super renderContentOn: html ].
         
-    self flushSelectorsCache
+    "self flushSelectorsCache"
 !
 
 renderItemLabel: aCompiledMethod on: html
@@ -393,14 +393,20 @@ renderItemLabel: aCompiledMethod on: html
 
 !HLMethodsListWidget methodsFor: 'testing'!
 
+isOverridden: aMethod
+   ^ self selectorsCache isOverridden: aMethod
+!
+
 isOverride: aMethod
+   ^ self selectorsCache isOverride: aMethod
+! !
 
-   ^ self overrideSelectors includes: aMethod selector
-!
+HLMethodsListWidget class instanceVariableNames: 'selectorsCache'!
 
-isOverriden: aMethod
+!HLMethodsListWidget class methodsFor: 'accessing'!
 
-   ^ self overridenSelectors includes: aMethod selector
+selectorsCache
+	^ HLSelectorsCache current
 ! !
 
 HLBrowserListWidget subclass: #HLPackagesListWidget
@@ -709,3 +715,133 @@ on: aBrowserModel
         yourself
 ! !
 
+Object subclass: #HLClassCache
+	instanceVariableNames: 'class parentCache overrideCache overriddenCache'
+	package: 'Helios-Browser'!
+
+!HLClassCache methodsFor: 'accessing'!
+
+overriddenCache
+	^ overriddenCache ifNil: [ overriddenCache := HashedCollection new ]
+!
+
+overrideCache
+	^ overrideCache ifNil: [ overrideCache := HashedCollection new ]
+!
+
+parentCache
+	^ parentCache
+!
+
+parentCache: aCache
+	parentCache := aCache
+!
+
+theClass
+	^ class
+!
+
+theClass: aClass
+	class := aClass
+! !
+
+!HLClassCache methodsFor: 'testing'!
+
+isOverridden: aMethod
+	^ self overriddenCache 
+    	at: aMethod selector
+      	ifAbsentPut: [ aMethod isOverridden ]
+!
+
+isOverride: aMethod
+	^ self overrideCache
+    	at: aMethod selector
+      	ifAbsentPut: [ aMethod isOverride ]
+! !
+
+!HLClassCache class methodsFor: 'instance creation'!
+
+on: aClass parentCache: aCache
+	^ self new
+    	theClass: aClass;
+        parentCache: aCache;
+        yourself
+! !
+
+Object subclass: #HLSelectorsCache
+	instanceVariableNames: 'classesCache'
+	package: 'Helios-Browser'!
+
+!HLSelectorsCache methodsFor: 'accessing'!
+
+cacheFor: aClass
+	aClass ifNil: [ ^ nil ].
+    
+	^ self classesCache
+    	at: aClass name
+        ifAbsentPut: [ self newCacheFor: aClass ]
+!
+
+classesCache
+	^ classesCache ifNil: [ classesCache := HashedCollection new ]
+! !
+
+!HLSelectorsCache methodsFor: 'factory'!
+
+newCacheFor: aClass
+	^ HLClassCache 
+    	on: aClass
+        parentCache: (self cacheFor: aClass superclass)
+! !
+
+!HLSelectorsCache methodsFor: 'testing'!
+
+isOverridden: aMethod
+	^ (self cacheFor: aMethod methodClass)
+    	isOverridden: aMethod
+!
+
+isOverride: aMethod
+	^ (self cacheFor: aMethod methodClass)
+    	isOverride: aMethod
+! !
+
+HLSelectorsCache class instanceVariableNames: 'current'!
+
+!HLSelectorsCache class methodsFor: 'accessing'!
+
+current
+	^ current ifNil: [ current := super new ]
+!
+
+flush
+	current := nil
+! !
+
+!HLSelectorsCache class methodsFor: 'instance creation'!
+
+new
+	self shouldNotImplement
+! !
+
+!CompiledMethod methodsFor: '*Helios-Browser'!
+
+isOverridden
+	| selector |
+    
+    selector := self selector.
+    self methodClass allSubclassesDo: [ :each |
+	    (each includesSelector: selector)
+        	ifTrue: [ ^ true ] ].
+	^ false
+!
+
+isOverride
+	| superclass |
+    
+    superclass := self methodClass superclass.
+	superclass ifNil: [ ^ false ].
+	
+    ^ (self methodClass superclass lookupSelector: self selector) isNil
+! !
+

+ 23 - 13
st/Kernel-Classes.st

@@ -130,19 +130,6 @@ protocols
    ^ self organization elements sorted
 !
 
-protocolsDo: aBlock
-	"Execute aBlock for each method category with
-	its collection of methods in the sort order of category name."
-
-	| methodsByCategory |
-	methodsByCategory := HashedCollection new.
-	self methodDictionary values do: [:m |
-		(methodsByCategory at: m category ifAbsentPut: [Array new])
- 			add: m]. 
-	self protocols do: [:category |
-		aBlock value: category value: (methodsByCategory at: category)]
-!
-
 prototype
 	<return self.fn.prototype>
 !
@@ -204,6 +191,29 @@ removeCompiledMethod: aMethod
             yourself)
 ! !
 
+!Behavior methodsFor: 'enumerating'!
+
+allSubclassesDo: aBlock
+	"Evaluate the argument, aBlock, for each of the receiver's subclasses."
+
+	self subclasses do: [ :each |
+    	aBlock value: each.
+        each allSubclassesDo: aBlock ].
+!
+
+protocolsDo: aBlock
+	"Execute aBlock for each method category with
+	its collection of methods in the sort order of category name."
+
+	| methodsByCategory |
+	methodsByCategory := HashedCollection new.
+	self methodDictionary values do: [:m |
+		(methodsByCategory at: m category ifAbsentPut: [Array new])
+ 			add: m]. 
+	self protocols do: [:category |
+		aBlock value: category value: (methodsByCategory at: category)]
+! !
+
 !Behavior methodsFor: 'instance creation'!
 
 basicNew