Added API for looking at module public functions.
authorDavid Anderson <dvander@alliedmods.net>
Sun Jul 08 17:57:44 2012 -0700 (2012-07-08)
changeset 6411c81eb30246
parent 63 dd57743d220e
child 65 7c942b5adebc
Added API for looking at module public functions.
include/keima.h
include/keima_util.h
jitcraft/API.cpp
jitcraft/BytecodeCompiler.cpp
jitcraft/BytecodeCompiler.h
jitcraft/BytecodeEmitter.h
jitcraft/Functions.cpp
jitcraft/Functions.h
jitcraft/Modules.cpp
jitcraft/Modules.h
jitcraft/ObjectVisitor.h
jitcraft/RootScopes.cpp
jitcraft/jitcraft.vcxproj
     1.1 --- a/include/keima.h	Sun Jul 08 16:49:17 2012 -0700
     1.2 +++ b/include/keima.h	Sun Jul 08 17:57:44 2012 -0700
     1.3 @@ -19,6 +19,7 @@
     1.4  #define _include_sourcepawn3_api_h_
     1.5  
     1.6  #include <stddef.h>
     1.7 +#include "../include/keima_util.h"
     1.8  
     1.9  namespace ke {
    1.10  
    1.11 @@ -31,6 +32,8 @@
    1.12  
    1.13  namespace Ke {
    1.14  
    1.15 +class Function;
    1.16 +
    1.17  /*
    1.18   * A Handle is a safe pointer that holds an object reference, such that it
    1.19   * can be scanned and potentially moved by the garbage collector.
    1.20 @@ -182,11 +185,35 @@
    1.21      void operator delete(void *, size_t);
    1.22  };
    1.23  
    1.24 +// A string is an immutable UTF8 buffer.
    1.25 +class KE_EXPORT String
    1.26 +{
    1.27 +  public:
    1.28 +    // Returns the length of the string, in bytes.
    1.29 +    unsigned length();
    1.30 +
    1.31 +    // Returns the character buffer of the string, or NULL on failure. If the
    1.32 +    // string is interned, chars() is guaranteed to succeed.
    1.33 +    const char *chars();
    1.34 +};
    1.35 +
    1.36 +// A function is an executable unit of code.
    1.37 +class KE_EXPORT Function
    1.38 +{
    1.39 +  public:
    1.40 +    // Returns the name of a function, which may be NULL. If not NULL, the
    1.41 +    // string is guaranteed to be interned/
    1.42 +    Local<String> name();
    1.43 +};
    1.44 +
    1.45  // A module represents a single compiled file, and contains functions and
    1.46  // global variables for that file (as well as exported types).
    1.47 -class Module
    1.48 +class KE_EXPORT Module
    1.49  {
    1.50    public:
    1.51 +    // Returns publics that are based on forwards.
    1.52 +    unsigned numPublics();
    1.53 +    Local<Function> getPublic(unsigned index);
    1.54  };
    1.55  
    1.56  class Keima
    1.57 @@ -215,9 +242,28 @@
    1.58       * until garbage collection completes.
    1.59       */
    1.60      static void CollectGarbage();
    1.61 +
    1.62 +    /*
    1.63 +     * Clear any pending exception.
    1.64 +     */
    1.65 +    static void ClearPendingException();
    1.66  };
    1.67  
    1.68  /*
    1.69 + * Suppresses exceptions. This is useful for calling API functions. When this
    1.70 + * in scope, errors will be reported, but the exception will be cleared after.
    1.71 + */
    1.72 +class AutoClearExceptions
    1.73 +{
    1.74 +  public:
    1.75 +    ~AutoClearExceptions()
    1.76 +    {
    1.77 +        Keima::ClearPendingException();
    1.78 +    }
    1.79 +};
    1.80 +
    1.81 +
    1.82 +/*
    1.83   * Compiles a file and returns a Module.
    1.84   */
    1.85  extern Local<Module> Compile(const char *path);
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/include/keima_util.h	Sun Jul 08 17:57:44 2012 -0700
     2.3 @@ -0,0 +1,33 @@
     2.4 +/*
     2.5 + * Copyright (C) 2004-2012 David Anderson
     2.6 + *
     2.7 + * This file is part of SourcePawn.
     2.8 + *
     2.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
    2.10 + * the terms of the GNU General Public License as published by the Free
    2.11 + * Software Foundation, either version 3 of the License, or (at your option)
    2.12 + * any later version.
    2.13 + * 
    2.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    2.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License along with
    2.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    2.20 + */
    2.21 +#ifndef _include_keima_util_h_
    2.22 +#define _include_keima_util_h_
    2.23 +
    2.24 +#if defined(_MSC_VER)
    2.25 +# if defined(KE_EXPORTING)
    2.26 +#   define KE_EXPORT __declspec(dllexport)
    2.27 +# elif defined(KE_IMPORTING)
    2.28 +#   define KE_EXPORT __declspec(dllimport)
    2.29 +# endif
    2.30 +#endif
    2.31 +
    2.32 +#if !defined(KE_EXPORT)
    2.33 +# define KE_EXPORT
    2.34 +#endif
    2.35 +
    2.36 +#endif // _include_keima_util_h_
     3.1 --- a/jitcraft/API.cpp	Sun Jul 08 16:49:17 2012 -0700
     3.2 +++ b/jitcraft/API.cpp	Sun Jul 08 17:57:44 2012 -0700
     3.3 @@ -74,8 +74,14 @@
     3.4      return *reinterpret_cast<To **>(*from);
     3.5  }
     3.6  
     3.7 +template <typename From, typename To> static inline To *
     3.8 +Open(From *from)
     3.9 +{
    3.10 +    return *reinterpret_cast<To **>(from);
    3.11 +}
    3.12 +
    3.13  template <typename From, typename To> static inline Ke::Local<To>
    3.14 -ToLocal(Handle<From> from)
    3.15 +ToLocal(From *from)
    3.16  {
    3.17      return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
    3.18  }
    3.19 @@ -192,3 +198,39 @@
    3.20  {
    3.21      ke::ZONE()->heap().reclaim();
    3.22  }
    3.23 +
    3.24 +unsigned
    3.25 +Ke::Module::numPublics()
    3.26 +{
    3.27 +    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
    3.28 +    return module->publics()->length();
    3.29 +}
    3.30 +
    3.31 +Ke::Local<Ke::Function>
    3.32 +Ke::Module::getPublic(unsigned index)
    3.33 +{
    3.34 +    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
    3.35 +    ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
    3.36 +    return ToLocal<ke::Function, Ke::Function>(fun);
    3.37 +}
    3.38 +
    3.39 +unsigned
    3.40 +Ke::String::length()
    3.41 +{
    3.42 +    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
    3.43 +    return obj->length();
    3.44 +}
    3.45 +
    3.46 +const char *
    3.47 +Ke::String::chars()
    3.48 +{
    3.49 +    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
    3.50 +    return obj->chars();
    3.51 +}
    3.52 +
    3.53 +Ke::Local<Ke::String>
    3.54 +Ke::Function::name()
    3.55 +{
    3.56 +    ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
    3.57 +    return ToLocal<ke::String, Ke::String>(fun->name());
    3.58 +}
     4.1 --- a/jitcraft/BytecodeCompiler.cpp	Sun Jul 08 16:49:17 2012 -0700
     4.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sun Jul 08 17:57:44 2012 -0700
     4.3 @@ -748,9 +748,21 @@
     4.4      if (!code)
     4.5          return NULL;
     4.6  
     4.7 -    Local<Function> fun(zone_, Function::New(zone_, module_, code, node->fun()->type(), node->pos()));
     4.8 +    Local<Type> type(zone_, node->fun()->type());
     4.9 +    Local<String> name(zone_, node->fun()->name());
    4.10 +    Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
    4.11      if (!fun)
    4.12          return NULL;
    4.13 +
    4.14 +    // If this function had a forward, export it as a named public.
    4.15 +    if (node->fun()->isPublic()) {
    4.16 +        assert(node->fun()->isPublic());
    4.17 +        ScopedRoot<Function> root(fun);
    4.18 +        if (!root)
    4.19 +            return NULL;
    4.20 +        if (!publics_.append(root))
    4.21 +            return NULL;
    4.22 +    }
    4.23      
    4.24      return fun;
    4.25  }
    4.26 @@ -772,5 +784,15 @@
    4.27          assert(module_->getFunction(i));
    4.28  #endif
    4.29  
    4.30 +    if (publics_.length()) {
    4.31 +        Local<Function> fun(zone_);
    4.32 +        Local<FixedArray> list(zone_, FixedArray::New(zone_, publics_.length(), Heap::Tenure_Old));
    4.33 +        if (!list)
    4.34 +            return NULL;
    4.35 +
    4.36 +        for (size_t i = 0; i < publics_.length(); i++)
    4.37 +            list->set(zone_, i, publics_[i]);
    4.38 +    }
    4.39 +
    4.40      return module_;
    4.41  }
     5.1 --- a/jitcraft/BytecodeCompiler.h	Sun Jul 08 16:49:17 2012 -0700
     5.2 +++ b/jitcraft/BytecodeCompiler.h	Sun Jul 08 17:57:44 2012 -0700
     5.3 @@ -35,6 +35,7 @@
     5.4      ScopedRoot<Module> module_;
     5.5      ScopedRoot<FixedArray> locals_;
     5.6      Scope *scope_;
     5.7 +    PoolList<ScopedRoot<Function> > publics_;
     5.8  
     5.9      class LoopScope
    5.10      {
     6.1 --- a/jitcraft/BytecodeEmitter.h	Sun Jul 08 16:49:17 2012 -0700
     6.2 +++ b/jitcraft/BytecodeEmitter.h	Sun Jul 08 17:57:44 2012 -0700
     6.3 @@ -30,7 +30,7 @@
     6.4  class Type;
     6.5  class Map;
     6.6  
     6.7 -typedef PoolList<ScopedRoot<Object> *> ObjectList;
     6.8 +typedef PoolList<ScopedRoot<Object>> ObjectList;
     6.9  
    6.10  struct OopRecord : public PoolObject
    6.11  {
    6.12 @@ -110,7 +110,7 @@
    6.13      }
    6.14      void writeObject(Object *obj) {
    6.15          writeUint32(objects_.length());
    6.16 -        ScopedRoot<Object> *root = new ScopedRoot<Object>(obj);
    6.17 +        ScopedRoot<Object> root(obj);
    6.18          if (!root)
    6.19              oom_ = true;
    6.20          oom_ &= objects_.append(root);
     7.1 --- a/jitcraft/Functions.cpp	Sun Jul 08 16:49:17 2012 -0700
     7.2 +++ b/jitcraft/Functions.cpp	Sun Jul 08 17:57:44 2012 -0700
     7.3 @@ -23,15 +23,16 @@
     7.4  using namespace ke;
     7.5  
     7.6  Function *
     7.7 -Function::New(Zone *zone, Module *module, Code *code, Type *type, const SourcePosition &pos)
     7.8 +Function::New(Zone *zone, Handle<Code> code, Handle<Type> type, Handle<String> name,
     7.9 +              const SourcePosition &pos)
    7.10  {
    7.11      Function *fun = Function::cast(zone->allocate(MapKind_Function, sizeof(Function), Heap::Tenure_Old));
    7.12      if (!fun)
    7.13          return NULL;
    7.14  
    7.15      fun->code_ = code;
    7.16 -    fun->module_ = module;
    7.17      fun->pos_ = pos;
    7.18      fun->type_ = type;
    7.19 +    fun->name_ = name;
    7.20      return fun;
    7.21  }
     8.1 --- a/jitcraft/Functions.h	Sun Jul 08 16:49:17 2012 -0700
     8.2 +++ b/jitcraft/Functions.h	Sun Jul 08 17:57:44 2012 -0700
     8.3 @@ -28,16 +28,17 @@
     8.4  class Code;
     8.5  class Module;
     8.6  class Type;
     8.7 +class String;
     8.8  
     8.9  class Function : public Object
    8.10  {
    8.11 -    Barriered<Module> module_;
    8.12      Barriered<Code> code_;
    8.13      Barriered<Type> type_;
    8.14 +    Barriered<String> name_;
    8.15      SourcePosition pos_;
    8.16  
    8.17   public:
    8.18 -    static Function *New(Zone *zone, Module *module, Code *code, Type *type,
    8.19 +    static Function *New(Zone *zone, Handle<Code> code, Handle<Type> type, Handle<String> name,
    8.20                           const SourcePosition &pos);
    8.21  
    8.22      Code *code() const {
    8.23 @@ -46,6 +47,9 @@
    8.24      Type *type() const {
    8.25          return type_;
    8.26      }
    8.27 +    String *name() const {
    8.28 +        return name_;
    8.29 +    }
    8.30      const SourcePosition &pos() {
    8.31          return pos_;
    8.32      }
    8.33 @@ -57,9 +61,6 @@
    8.34      }
    8.35  
    8.36      // Begin GC Descriptor.
    8.37 -    static inline size_t offsetOfModule() {
    8.38 -        return offsetof(Function, module_);
    8.39 -    }
    8.40      static inline size_t offsetOfCode() {
    8.41          return offsetof(Function, code_);
    8.42      }
     9.1 --- a/jitcraft/Modules.cpp	Sun Jul 08 16:49:17 2012 -0700
     9.2 +++ b/jitcraft/Modules.cpp	Sun Jul 08 17:57:44 2012 -0700
     9.3 @@ -34,5 +34,6 @@
     9.4          return NULL;
     9.5  
     9.6      module->functions_ = functions;
     9.7 +    module->publics_ = NULL;
     9.8      return module;
     9.9  }
    10.1 --- a/jitcraft/Modules.h	Sun Jul 08 16:49:17 2012 -0700
    10.2 +++ b/jitcraft/Modules.h	Sun Jul 08 17:57:44 2012 -0700
    10.3 @@ -27,6 +27,7 @@
    10.4  class Module : public Object
    10.5  {
    10.6      Barriered<FixedArray> functions_;
    10.7 +    Barriered<FixedArray> publics_;
    10.8  
    10.9    public:
   10.10      static Module *New(Zone *zone, unsigned nfunctions);
   10.11 @@ -40,10 +41,20 @@
   10.12          functions_->set(zone, i, fun);
   10.13      }
   10.14  
   10.15 +    FixedArray *publics() {
   10.16 +        return publics_;
   10.17 +    }
   10.18 +    void setPublics(Handle<FixedArray> publics) {
   10.19 +        publics_ = publics;
   10.20 +    }
   10.21 +
   10.22      // Begin GC Descriptor.
   10.23      static inline size_t offsetOfFunctions() {
   10.24          return offsetof(Module, functions_);
   10.25      }
   10.26 +    static inline size_t offsetOfPublics() {
   10.27 +        return offsetof(Module, publics_);
   10.28 +    }
   10.29      // End GC Descriptor.
   10.30  
   10.31      static inline Module *cast(Object *obj) {
    11.1 --- a/jitcraft/ObjectVisitor.h	Sun Jul 08 16:49:17 2012 -0700
    11.2 +++ b/jitcraft/ObjectVisitor.h	Sun Jul 08 17:57:44 2012 -0700
    11.3 @@ -78,11 +78,11 @@
    11.4  
    11.5      size_t iterateModule(Object *obj) {
    11.6          visitField(obj, Module::offsetOfFunctions());
    11.7 +        visitField(obj, Module::offsetOfPublics());
    11.8          return sizeof(Module);
    11.9      }
   11.10  
   11.11      size_t iterateFunction(Object *obj) {
   11.12 -        visitField(obj, Function::offsetOfModule());
   11.13          visitField(obj, Function::offsetOfCode());
   11.14          visitField(obj, Function::offsetOfType());
   11.15          return sizeof(Function);
    12.1 --- a/jitcraft/RootScopes.cpp	Sun Jul 08 16:49:17 2012 -0700
    12.2 +++ b/jitcraft/RootScopes.cpp	Sun Jul 08 17:57:44 2012 -0700
    12.3 @@ -16,6 +16,8 @@
    12.4   * You should have received a copy of the GNU General Public License along with
    12.5   * JITCraft. If not, see http://www.gnu.org/licenses/.
    12.6   */
    12.7 +#include <stdio.h>
    12.8 +#include <stdlib.h>
    12.9  #include "RootScopes.h"
   12.10  
   12.11  using namespace ke;
   12.12 @@ -42,8 +44,12 @@
   12.13      assert(blocks_->cur == blocks_->end);
   12.14  
   12.15      Block *block = new Block(blocks_);
   12.16 -    if (!block)
   12.17 +    if (!block) {
   12.18 +        // :TODO: We are not prepared for this...
   12.19 +        fprintf(stderr, "Could not allocate a local root scope.\n");
   12.20 +        abort();
   12.21          return false;
   12.22 +    }
   12.23  
   12.24      blocks_ = block;
   12.25      return true;
    13.1 --- a/jitcraft/jitcraft.vcxproj	Sun Jul 08 16:49:17 2012 -0700
    13.2 +++ b/jitcraft/jitcraft.vcxproj	Sun Jul 08 17:57:44 2012 -0700
    13.3 @@ -60,7 +60,7 @@
    13.4        </PrecompiledHeader>
    13.5        <WarningLevel>Level3</WarningLevel>
    13.6        <Optimization>Disabled</Optimization>
    13.7 -      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
    13.8 +      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS;KE_EXPORTING</PreprocessorDefinitions>
    13.9      </ClCompile>
   13.10      <Link>
   13.11        <SubSystem>Console</SubSystem>
   13.12 @@ -127,6 +127,7 @@
   13.13    </ItemGroup>
   13.14    <ItemGroup>
   13.15      <ClInclude Include="..\include\keima.h" />
   13.16 +    <ClInclude Include="..\include\keima_util.h" />
   13.17      <ClInclude Include="AllocatorPolicies.h" />
   13.18      <ClInclude Include="Array.h" />
   13.19      <ClInclude Include="AST.h" />