[vmkit-commits] [vmkit] r54579 - in /vmkit/trunk/lib/N3/VMCore: Assembly.cpp Assembly.h CLIJit.cpp CLISignature.cpp N3Initialise.cpp Opcodes.cpp VMArray.cpp VMArray.h VMClass.cpp VMClass.h VMThread.cpp VMThread.h VirtualTables.cpp

Tilmann Scheller tilmann.scheller at googlemail.com
Sat Aug 9 03:23:36 PDT 2008


Author: tilmann
Date: Sat Aug  9 05:23:35 2008
New Revision: 54579

URL: http://llvm.org/viewvc/llvm-project?rev=54579&view=rev
Log:
add support for generic methods to N3
fix bug in box instruction

Modified:
    vmkit/trunk/lib/N3/VMCore/Assembly.cpp
    vmkit/trunk/lib/N3/VMCore/Assembly.h
    vmkit/trunk/lib/N3/VMCore/CLIJit.cpp
    vmkit/trunk/lib/N3/VMCore/CLISignature.cpp
    vmkit/trunk/lib/N3/VMCore/N3Initialise.cpp
    vmkit/trunk/lib/N3/VMCore/Opcodes.cpp
    vmkit/trunk/lib/N3/VMCore/VMArray.cpp
    vmkit/trunk/lib/N3/VMCore/VMArray.h
    vmkit/trunk/lib/N3/VMCore/VMClass.cpp
    vmkit/trunk/lib/N3/VMCore/VMClass.h
    vmkit/trunk/lib/N3/VMCore/VMThread.cpp
    vmkit/trunk/lib/N3/VMCore/VMThread.h
    vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp

Modified: vmkit/trunk/lib/N3/VMCore/Assembly.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Assembly.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Assembly.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/Assembly.cpp Sat Aug  9 05:23:35 2008
@@ -420,17 +420,40 @@
   return meth;
 }
 
+static VMGenericMethod* genMethodDup(uint32& key, Assembly* ass) {
+  VMGenericMethod* meth = gc_new(VMGenericMethod)();
+  meth->token = key;
+  meth->canBeInlined = false;
+  return meth;
+}
+
 VMMethod* Assembly::constructMethod(VMClass* cl, const UTF8* name, 
-                                    uint32 token) {
+                                    uint32 token, bool generic) {
   VMMethod* meth;
   
-  if (VMThread::get()->currGenericClass == 0) {
+  if (VMThread::get()->currGenericClass == 0 && generic == false) {
     // we are not reading a generic class 
     meth = loadedTokenMethods->lookupOrCreate(token, this, methodDup);
   } else {
-    // we are reading a generic class, don't add a reference
+    // we are reading a generic class or a generic method, don't add a reference
     // to the loadedTokenMethods map
     meth = methodDup(token, this);
+    
+    if (generic) {
+      // we are reading a generic method
+      if (VMThread::get()->genMethodInstantiation == NULL) {
+        cl->genericMethods.push_back(meth);
+      } else {
+        VMGenericMethod* genMethod = genMethodDup(token, this);
+        genMethod->genericParams = *VMThread::get()->genMethodInstantiation;
+        meth = genMethod;
+        if (isStatic(meth->flags)) {
+          cl->staticMethods.push_back(meth);
+        } else {
+          cl->virtualMethods.push_back(meth);
+        }
+      }
+    }
   }
   
   meth->classDef = cl;
@@ -1323,43 +1346,42 @@
   uint32 paramList  = methArray[CONSTANT_METHODDEF_PARAMLIST];
   
   uint32 offset = blobOffset + signature;
-  
-  if (isGenericMethod(offset)) {
-    // generic methods are read on instantiation
-    return NULL;
+
+  VMMethod* meth = 
+    constructMethod((VMClass*)cl, readString(cl->vm, (name + stringOffset)),
+                    token, isGenericMethod(offset));
+  
+  offset = blobOffset + signature;
+  
+  VMGenericMethod* tmp = VMThread::get()->currGenericMethod;
+  VMThread::get()->currGenericMethod = dynamic_cast<VMGenericMethod*>(meth);
+  meth->virt = extractMethodSignature(offset, cl, meth->parameters);
+  VMThread::get()->currGenericMethod = tmp;
+  
+  meth->flags = flags;
+  meth->implFlags = implFlags;
+
+  if (rva) {
+    meth->offset = textSection->rawAddress + 
+                   (rva - textSection->virtualAddress);
   } else {
-    offset = blobOffset + signature;
-    
-    VMMethod* meth = 
-      constructMethod((VMClass*)cl, readString(cl->vm, (name + stringOffset)),
-                      token);
-    meth->virt = extractMethodSignature(offset, cl, meth->parameters);
-    meth->flags = flags;
-    meth->implFlags = implFlags;
-  
-    if (rva) {
-      meth->offset = textSection->rawAddress + 
-                     (rva - textSection->virtualAddress);
-    } else {
-      meth->offset = 0;
-    }
-  
-    if (paramList && paramTable != 0 && paramList <= paramSize) {
-      uint32 endParam = (index == methodSize) ? 
-          paramSize + 1 : 
-          methTable->readIndexInRow(index + 1, CONSTANT_METHODDEF_PARAMLIST,
-                                  bytes);
+    meth->offset = 0;
+  }
 
-      uint32 nbParams = endParam - paramList;
+  if (paramList && paramTable != 0 && paramList <= paramSize) {
+    uint32 endParam = (index == methodSize) ? 
+        paramSize + 1 : 
+        methTable->readIndexInRow(index + 1, CONSTANT_METHODDEF_PARAMLIST,
+                                bytes);
 
-      for (uint32 j = 0; j < nbParams; ++j) {
-        meth->params.push_back(readParam(j + paramList, meth));
-      }
+    uint32 nbParams = endParam - paramList;
 
+    for (uint32 j = 0; j < nbParams; ++j) {
+      meth->params.push_back(readParam(j + paramList, meth));
     }
-
-    return meth;
   }
+
+  return meth;
 }
 
 VMField* Assembly::readField(uint32 index, VMCommonClass* cl) {
@@ -1637,7 +1659,7 @@
       }
 
       case CONSTANT_MemberRef : {
-        meth = readMemberRefAsMethod(token);
+        meth = readMemberRefAsMethod(token, NULL);
         break;
       }
       
@@ -1679,7 +1701,7 @@
   return i + 1 + (CONSTANT_TypeDef << 24);
 }
 
-VMMethod* Assembly::readMemberRefAsMethod(uint32 token) {
+VMMethod* Assembly::readMemberRefAsMethod(uint32 token, std::vector<VMCommonClass*>* genArgs) {
   uint32 index = token & 0xffff;
   Table* memberTable = CLIHeader->tables[CONSTANT_MemberRef];
   uint32* memberArray = (uint32*)alloca(sizeof(uint32) * memberTable->rowSize);
@@ -1706,7 +1728,34 @@
       VMCommonClass* type = loadType(((N3*)VMThread::get()->vm), typeToken,
                                      true, false, false, true);
       bool virt = extractMethodSignature(offset, type, args);
-      VMMethod* meth = type->lookupMethod(name, args, !virt, true);
+      VMMethod* meth;
+      
+      if (genArgs != NULL) {
+        VMClass* cl = dynamic_cast<VMClass*>(type);
+        
+        if (cl == NULL) {
+          VMThread::get()->vm->error("Only instances of generic classes are allowed.");
+        }
+        
+        // search for matching signature
+        for (uint i = 0; i < cl->genericMethods.size(); ++i) {
+          VMMethod* genMethod = cl->genericMethods.at(i);
+          
+          if (!name->equals(genMethod->name) || !genMethod->signatureEqualsGeneric(args)) {
+            continue;
+          }
+        
+          // use found token to create instance of generic method
+          VMThread::get()->genMethodInstantiation = genArgs;
+          meth = readMethodDef(genMethod->token & 0xFFFFFF, type);
+          VMThread::get()->genMethodInstantiation = NULL;
+          meth->token = token;
+          // insert in global hashmap
+        }
+      } else {
+        meth = type->lookupMethod(name, args, !virt, true);
+      }
+
       return meth;
     }
 
@@ -1781,7 +1830,7 @@
     }
     case 1 : {
       methodToken = index + (CONSTANT_MemberRef << 24);
-      return readMemberRefAsMethod(methodToken);
+      return readMemberRefAsMethod(methodToken, &genArgs);
     }
   }
   

Modified: vmkit/trunk/lib/N3/VMCore/Assembly.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Assembly.h?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Assembly.h (original)
+++ vmkit/trunk/lib/N3/VMCore/Assembly.h Sat Aug  9 05:23:35 2008
@@ -150,7 +150,7 @@
   VMField*      constructField(VMClass* cl, const UTF8* name,
                                VMCommonClass* signature, uint32 token);
   VMMethod*     constructMethod(VMClass* cl, const UTF8* name,
-                                uint32 token);
+                                uint32 token, bool generic);
   VMCommonClass* lookupClassFromName(const UTF8* name, const UTF8* nameSpace);
   VMCommonClass* lookupClassFromToken(uint32 token);
   VMMethod* lookupMethodFromToken(uint32 token);
@@ -248,7 +248,7 @@
   
   VMMethod* getMethodFromToken(uint32 token); 
   uint32 getTypedefTokenFromMethod(uint32 token);
-  VMMethod* readMemberRefAsMethod(uint32 token);
+  VMMethod* readMemberRefAsMethod(uint32 token, std::vector<VMCommonClass*>* genArgs);
 
   const UTF8* readUserString(uint32 token); 
   uint32 getExplicitLayout(uint32 token);

Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Sat Aug  9 05:23:35 2008
@@ -1462,13 +1462,16 @@
   jit->compilingClass = cl; 
   jit->compilingMethod = meth;
 
-  // save previous generic class
+  // save previous generic and method class
   VMGenericClass* old = VMThread::get()->currGenericClass;
+  VMGenericMethod* oldMethod = VMThread::get()->currGenericMethod;
   
   // temporarily store the class of the method to be compiled
-  // in case it is a generic class
+  // in case it is a generic class 
   VMThread::get()->currGenericClass = dynamic_cast<VMGenericClass*>(cl);
   
+  VMThread::get()->currGenericMethod = dynamic_cast<VMGenericMethod*>(meth);
+  
   Function* func;
   meth->getSignature();
   
@@ -1483,6 +1486,8 @@
   // restore saved class
   VMThread::get()->currGenericClass = old;
   
+  VMThread::get()->currGenericMethod = oldMethod;
+  
   return func;
 }
 

Modified: vmkit/trunk/lib/N3/VMCore/CLISignature.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLISignature.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/CLISignature.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/CLISignature.cpp Sat Aug  9 05:23:35 2008
@@ -249,8 +249,18 @@
 }
 
 static VMCommonClass* METHOD_ElementTypeMvar(uint32 op, Assembly* ass, uint32& offset) {
-  VMThread::get()->vm->error("implement me");
-  return 0;
+  uint32 number = ass->uncompressSignature(offset);
+  
+  if (VMThread::get()->currGenericMethod == NULL) {
+    // return dummy VMClass, use the token field
+    // to store the generic argument number
+    VMClass* cl = gc_new(VMClass)();
+    cl->token = number;
+    cl->assembly = NULL;
+    return cl;
+  } else {
+    return VMThread::get()->currGenericMethod->genericParams[number];
+  }
 }
 
 static VMCommonClass* METHOD_ElementTypeCmodReqd(uint32 op, Assembly* ass, uint32& offset) {
@@ -365,11 +375,16 @@
   //uint32 count      = 
   uncompressSignature(offset);
   uint32 call       = uncompressSignature(offset);
+  
+  if (call & CONSTANT_Generic) {
+    //uint32 genArgCount =
+    uncompressSignature(offset);
+  }
+  
   uint32 paramCount = uncompressSignature(offset);
 
   uint32 hasThis = call & CONSTANT_HasThis ? 1 : 0;
   uint32 realCount = paramCount + hasThis;
-  //uint32 generic = call & CONSTANT_Generic ? 1 : 0;
 
   VMCommonClass* ret = exploreType(offset);
   types.push_back(ret);
@@ -377,6 +392,7 @@
   if (hasThis) {
     types.push_back(cl);
   }
+  
   for (uint32 i = hasThis; i < realCount; ++i) {
     VMCommonClass* cur = exploreType(offset);
     types.push_back(cur);

Modified: vmkit/trunk/lib/N3/VMCore/N3Initialise.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/N3Initialise.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/N3Initialise.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/N3Initialise.cpp Sat Aug  9 05:23:35 2008
@@ -187,8 +187,10 @@
   INIT(UTF8);
   INIT(VMCommonClass);
   INIT(VMClass);
+  INIT(VMGenericClass);
   INIT(VMClassArray);
   INIT(VMMethod);
+  INIT(VMGenericMethod);
   INIT(VMField);
   INIT(VMCond);
   INIT(LockObj);

Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Sat Aug  9 05:23:35 2008
@@ -1280,6 +1280,11 @@
         VMCommonClass* type = assembly->loadType(vm, token, true, false, false,
                                                  true);
         assert(type);
+        
+        if (!type->isPrimitive) {
+          // the box instruction has no effect on non-primitive types
+          break;
+        }
 
         Value* var = new LoadInst(type->llvmVar(), "", currentBlock);
         Value* obj = CallInst::Create(objConsLLVM, var, "", currentBlock);

Modified: vmkit/trunk/lib/N3/VMCore/VMArray.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMArray.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMArray.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VMArray.cpp Sat Aug  9 05:23:35 2008
@@ -218,3 +218,20 @@
   return buf->cString();
 }
 
+bool UTF8::equals(const UTF8 *string) const
+{
+  if (size != string->size) {
+    return false;
+  }
+  
+  for (sint32 i = 0; i < size; ++i) {
+    if (at(i) != string->at(i)) {
+      return false;
+    }
+  }
+  
+  return true;
+}
+
+
+

Modified: vmkit/trunk/lib/N3/VMCore/VMArray.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMArray.h?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMArray.h (original)
+++ vmkit/trunk/lib/N3/VMCore/VMArray.h Sat Aug  9 05:23:35 2008
@@ -104,6 +104,8 @@
   static const UTF8* readerConstruct(VirtualMachine *vm, uint16* buf, uint32 n);
 
   const UTF8* extract(VirtualMachine *vm, uint32 start, uint32 len) const;
+  
+  bool equals(const UTF8* string) const;
 };
 
 } // end namespace n3

Modified: vmkit/trunk/lib/N3/VMCore/VMClass.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMClass.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VMClass.cpp Sat Aug  9 05:23:35 2008
@@ -110,6 +110,32 @@
   buf->write(">");
 }
 
+void VMGenericMethod::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIGenericMethod<");
+  classDef->nameSpace->print(buf);
+  buf->write(".");
+  classDef->name->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write("(");
+  std::vector<VMCommonClass*>::iterator i = ((VMMethod*)this)->parameters.begin();
+  std::vector<VMCommonClass*>::iterator e = ((VMMethod*)this)->parameters.end();
+
+  ++i;
+  if (i != e) {
+    while (true) {
+      (*i)->nameSpace->print(buf);
+      buf->write(".");
+      (*i)->name->print(buf);
+      ++i;
+      if (i == e) break;
+      else buf->write(" ,");
+    }
+  }
+  buf->write(")");
+  buf->write(">");
+}
+
 void VMField::print(mvm::PrintBuffer* buf) const {
   buf->write("CLIField<");
   classDef->nameSpace->print(buf);
@@ -796,9 +822,59 @@
   return true;
 }
 
+bool VMMethod::signatureEqualsGeneric(std::vector<VMCommonClass*> & args) {
+	bool stat = isStatic(flags);
+
+	if (args.size() != parameters.size())
+		return false;
+	else {
+		std::vector<VMCommonClass*>::iterator i = parameters.begin(), a =
+				args.begin(), e = args.end();
+
+		if (((*i)->assembly == NULL && (*a)->assembly != NULL) ||
+		    ((*i)->assembly != NULL && (*a)->assembly == NULL))
+		  return false;
+		
+		if ((*i)->assembly == NULL && (*a)->assembly == NULL) {
+		  if ((*i)->token != (*a)->token) {
+		    return false;
+		  }
+		}
+		
+		if ((*i) != (*a))
+			return false;
+		++i;
+		++a;
+
+		if (!stat) {
+			++i;
+			++a;
+		}
+
+		for (; a != e; ++i, ++a) {
+	    if (((*i)->assembly == NULL && (*a)->assembly != NULL) ||
+	        ((*i)->assembly != NULL && (*a)->assembly == NULL))
+	      return false;
+	    
+	    if ((*i)->assembly == NULL && (*a)->assembly == NULL) {
+	      if ((*i)->token != (*a)->token) {
+	        return false;
+	      } else {
+	        continue;
+	      }
+	    }
+	    
+			if ((*i) != (*a))
+				return false;
+		}
+	}
+	return true;
+}
+
 void VMGenericClass::print(mvm::PrintBuffer* buf) const {
   buf->write("GenCLIType<");
   nameSpace->print(buf);
   buf->write("::");
   name->print(buf);
-  buf->write(">");}
+  buf->write(">");
+}

Modified: vmkit/trunk/lib/N3/VMCore/VMClass.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.h?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMClass.h (original)
+++ vmkit/trunk/lib/N3/VMCore/VMClass.h Sat Aug  9 05:23:35 2008
@@ -141,6 +141,7 @@
   VMObject* virtualInstance;
   std::vector<VMClass*> innerClasses;
   VMClass* outerClass;
+  std::vector<VMMethod*> genericMethods;
   
   VMObject* operator()();
   VMObject* doNew();
@@ -229,10 +230,20 @@
   static const llvm::FunctionType* resolveSignature(
       std::vector<VMCommonClass*>& params, bool isVirt, bool &structRet);
   bool signatureEquals(std::vector<VMCommonClass*>& args);
+  bool signatureEqualsGeneric(std::vector<VMCommonClass*>& args);
   llvm::GlobalVariable* llvmVar();
   llvm::GlobalVariable* _llvmVar;
 };
 
+class VMGenericMethod : public VMMethod {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void TRACER;
+
+  std::vector<VMCommonClass*> genericParams;
+};
+
 class VMField : public mvm::Object {
 public:
   static VirtualTable* VT;

Modified: vmkit/trunk/lib/N3/VMCore/VMThread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMThread.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMThread.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VMThread.cpp Sat Aug  9 05:23:35 2008
@@ -59,7 +59,10 @@
   key->self = mvm::Thread::self();
   key->pendingException = 0;
   key->perFunctionPasses = new llvm::FunctionPassManager(vm->TheModuleProvider);
-  key->perFunctionPasses->add(new llvm::TargetData(vm->module)); 
+  key->perFunctionPasses->add(new llvm::TargetData(vm->module));
+  key->currGenericClass = NULL;
+  key->currGenericMethod = NULL;
+  key->genMethodInstantiation = NULL;
   AddStandardCompilePasses(key->perFunctionPasses);
   return key;
 }

Modified: vmkit/trunk/lib/N3/VMCore/VMThread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMThread.h?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMThread.h (original)
+++ vmkit/trunk/lib/N3/VMCore/VMThread.h Sat Aug  9 05:23:35 2008
@@ -26,6 +26,7 @@
 class VMClass;
 class VMGenericClass;
 class VMObject;
+class VMGenericMethod;
 
 class VMThread : public mvm::Thread {
 public:
@@ -42,6 +43,11 @@
   
   // helper which points to the current generic class
   VMGenericClass* currGenericClass;
+  // helper which contains the instantiation of the
+  // current generic method
+  std::vector<VMCommonClass*>* genMethodInstantiation;
+  // helper which points to the current generic method
+  VMGenericMethod* currGenericMethod;
 
   static const unsigned int StateRunning;
   static const unsigned int StateWaiting;

Modified: vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp?rev=54579&r1=54578&r2=54579&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp Sat Aug  9 05:23:35 2008
@@ -44,6 +44,7 @@
   INIT(VMClassArray);
   INIT(VMClassPointer);
   INIT(VMMethod);
+  INIT(VMGenericMethod);
   INIT(VMField);
   INIT(VMCond);
   INIT(LockObj);
@@ -168,6 +169,7 @@
   virtualInstance->MARK_AND_TRACE;
   TRACE_VECTOR(VMClass*, innerClasses, std::allocator);
   outerClass->MARK_AND_TRACE;
+  TRACE_VECTOR(VMMethod*, genericMethods, std::allocator);
 }
 
 void VMGenericClass::TRACER {
@@ -195,6 +197,11 @@
   name->MARK_AND_TRACE;
 }
 
+void VMGenericMethod::TRACER {
+  VMMethod::PARENT_TRACER;
+  TRACE_VECTOR(VMCommonClass*, genericParams, std::allocator);
+}
+
 void VMField::TRACER {
   signature->MARK_AND_TRACE;
   classDef->MARK_AND_TRACE;





More information about the vmkit-commits mailing list