/* Sun-$Revision: 23.6 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
See the LICENSE file for license information. */
# pragma interface
enum LookupStatus {
foundNone,
foundOne,
foundSeveral,
foundAssignableParent,
resendUndecidable,
delegateeNotFound,
mismatchedArgCount,
performTypeError
};
enum ResultType {
methodResult,
constantResult,
dataResult,
assignmentResult
};
char* lookupStatusString(LookupStatus l);
class simpleLookup: public ResourceObj {
public:
MethodLookupKey key;
oop receiver; // badOop if none
LookupStatus status;
protected:
abstractSlotRef* _result;
public:
// set to NULL for no tracking:
dependencyList* deps;
assignableDependencyList* adeps;
simpleLookup(LookupType l,
oop rcvr,
oop sel,
oop dgt,
oop mhOrMap,
dependencyList* dps = NULL,
assignableDependencyList* adps = NULL);
LookupType lookupType() { return key.lookupType; }
oop selector() { return key.selector; }
oop delegatee() { return key.delegatee; }
Map* receiverMap() { return key.receiverMap(); }
mapOop receiverMapOop() { return key.receiverMapOop(); }
oop methodHolder_or_map() { return key.methodHolder_or_map(); }
Map* methodHolder_map() {
oop m= methodHolder_or_map();
assert (m != MH_TBD && m != MH_NOT_A_RESEND, "no method holder");
return m->is_map() ? mapOop(m)->addr() : m->map();
}
abstractSlotRef* result() { return _result; }
bool isReceiverStatic() { return lookupType() & ReceiverStaticBit; }
bool isDelegateeStatic() { return lookupType() & DelegateeStaticBit; }
bool isPerform() { return isPerformLookupType(lookupType()); }
bool isImplicitSelf() { return lookupType() & ImplicitSelfBit; }
void clearReceiverStatic() { key.lookupType &= ~ReceiverStaticBit; }
// Used only when we actually know the lookup result in advance.
inline void setResult(oop resultMethod, oop resultMethodHolder = MH_NOT_A_RESEND);
virtual void perform_lookup();
virtual bool is_for_inlining() { return false; }
void perform_full_lookup_n( int32 perform_arg_count );
fint arg_count() {
oop s= selector();
return s && s->is_string() ? stringOop(s)->arg_count() : 0; }
ResultType resultType();
oop evaluateResult(oop* argp, int32 nargs, nmethod* nm);
char* interpretResultForCompiledSender(oop arg1);
protected:
lookupTarget* create_initial_target();
// kinds of initial targets
virtual lookupTarget* receiver_lookup_target();
virtual lookupTarget* delegated_lookup_target();
virtual lookupTarget* directed_resend_lookup_target();
virtual lookupTarget* undirected_resend_lookup_target();
// simple lookup is too simple to look for locals,
// so just pretend its the receiver
virtual lookupTarget* implicit_self_lookup_target() {
return receiver_lookup_target(); }
virtual bool check_slot_for_directed_resend(slotDesc*);
bool objectLookup(lookupTarget* target);
bool parentsLookup(lookupTarget* target);
// the entry point for this group
void lookupErrorCode(int32 perform_arg_count);
void handleRecursiveLookupError();
void generateLookupErrorMethod(int32 perform_arg_count);
// helpers for above fn:
void selectorAndSourceForLookupError(stringOop& sel, char*& src);
stringOop messageTypeForLookupError();
int32 argCountForLookupError(int32 perform_arg_count);
LookupStatus perform_error_status(int32 perform_arg_count);
public:
void remove_all_deps() {
if ( deps != NULL) deps->remove();
if ( adeps != NULL) adeps->remove(); }
void add_dependency(slotDesc* s, Map* map) {
if ( deps == NULL ) return;
if (map->is_block()) return;
if (s == NULL || s->is_parent()) {
deps->add(map);
} else if (map->can_have_dependents()) {
assert(s >= map->slots() && s < map->slot(map->length_slots()),
"slotDesc not in map");
deps->add((slotsMapDeps*)map, s);
} }
void add_slot_dependency(Map* map) {
if ( deps == NULL ) return;
deps->add(map); }
void add_asg_parent_dependency(objectLookupTarget* otarg,
objectLookupTarget* ntarg,
slotDesc* sd);
virtual void print();
protected:
inline void assert_static_selector();
inline void assert_static_delegatee();
inline void assert_methodHolder_is_object();
};