Convert Name and StringPool to a GC-safe symbol table.
Convert Name and StringPool to a GC-safe symbol table.
1.1 --- a/jitcraft/AST.h Sat Jul 07 17:11:31 2012 -0700
1.2 +++ b/jitcraft/AST.h Sat Jul 07 20:28:29 2012 -0700
1.3 @@ -20,8 +20,8 @@
1.4
1.5 #include "PoolAllocator.h"
1.6 #include "Token.h"
1.7 -#include "StringPool.h"
1.8 #include "NameBinding.h"
1.9 +#include <vector>
1.10
1.11 namespace jc {
1.12
1.13 @@ -160,10 +160,10 @@
1.14 Variable *variable_;
1.15 Expression *initialization_;
1.16 ExpressionList *postDimensions_;
1.17 - Name *tag_;
1.18 + ScopedRoot<String> tag_;
1.19
1.20 public:
1.21 - VariableDeclaration(const SourcePosition &pos, Variable *var, Name *tag,
1.22 + VariableDeclaration(const SourcePosition &pos, Variable *var, Handle<String> tag,
1.23 ExpressionList *postDimensions, Expression *initialization)
1.24 : Statement(pos),
1.25 variable_(var),
1.26 @@ -173,7 +173,7 @@
1.27 {
1.28 }
1.29
1.30 - Name *tag() const {
1.31 + String *tag() const {
1.32 return tag_;
1.33 }
1.34 Kind kind() const {
1.35 @@ -196,18 +196,18 @@
1.36 class Parameter : public PoolObject
1.37 {
1.38 Variable *variable_;
1.39 - Name *tag_;
1.40 + ScopedRoot<String> tag_;
1.41 bool reference_;
1.42
1.43 public:
1.44 - Parameter(Variable *var, Name *tag, bool reference)
1.45 + Parameter(Variable *var, Handle<String> tag, bool reference)
1.46 : variable_(var),
1.47 tag_(tag),
1.48 reference_(reference)
1.49 {
1.50 }
1.51
1.52 - Name *tag() const {
1.53 + String *tag() const {
1.54 return tag_;
1.55 }
1.56 Variable *variable() const {
1.57 @@ -220,11 +220,11 @@
1.58
1.59 class NameProxy : public Expression
1.60 {
1.61 - Name *name_;
1.62 + ScopedRoot<String> name_;
1.63 BoundName *binding_;
1.64
1.65 public:
1.66 - NameProxy(const SourcePosition &pos, Name *name, BoundName *binding)
1.67 + NameProxy(const SourcePosition &pos, Handle<String> name, BoundName *binding)
1.68 : Expression(pos),
1.69 name_(name),
1.70 binding_(binding)
1.71 @@ -234,7 +234,7 @@
1.72 Kind kind() const {
1.73 return kNameProxy;
1.74 }
1.75 - Name *name() const {
1.76 + String *name() const {
1.77 return name_;
1.78 }
1.79 void accept(AstVisitor *visitor) {
1.80 @@ -688,7 +688,7 @@
1.81
1.82 class EnumStatement : public Statement
1.83 {
1.84 - Name *name_;
1.85 + ScopedRoot<String> name_;
1.86
1.87 public:
1.88 struct Entry {
1.89 @@ -705,7 +705,7 @@
1.90 typedef std::vector<Entry> EntryList;
1.91
1.92 public:
1.93 - EnumStatement(const SourcePosition &pos, Name *name, EntryList *entries)
1.94 + EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
1.95 : Statement(pos),
1.96 name_(name),
1.97 entries_(entries)
1.98 @@ -715,7 +715,7 @@
1.99 Kind kind() const {
1.100 return kEnumStatement;
1.101 }
1.102 - Name *name() const {
1.103 + String *name() const {
1.104 return name_;
1.105 }
1.106 EntryList *entries() const {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/jitcraft/AllocatorPolicies.h Sat Jul 07 20:28:29 2012 -0700
2.3 @@ -0,0 +1,45 @@
2.4 +/*
2.5 + * Copyright (C) 2012 David Anderson
2.6 + *
2.7 + * This file is part of JITCraft.
2.8 + *
2.9 + * JITCraft 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 + * Foobar 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 + * JITCraft. If not, see http://www.gnu.org/licenses/.
2.20 + */
2.21 +#ifndef _include_jc_allocators_h_
2.22 +#define _include_jc_allocators_h_
2.23 +
2.24 +#include <stdlib.h>
2.25 +
2.26 +namespace jc {
2.27 +
2.28 +class ZoneAllocatorPolicy
2.29 +{
2.30 + protected:
2.31 + void reportOutOfMemory();
2.32 + void reportAllocationOverflow();
2.33 +
2.34 + public:
2.35 + void free(void *memory) {
2.36 + ::free(memory);
2.37 + }
2.38 + void *malloc(size_t bytes) {
2.39 + void *ptr = ::malloc(bytes);
2.40 + if (!ptr)
2.41 + reportOutOfMemory();
2.42 + return ptr;
2.43 + }
2.44 +};
2.45 +
2.46 +}
2.47 +
2.48 +#endif // _include_jc_allocators_h_
3.1 --- a/jitcraft/BytecodeCompiler.cpp Sat Jul 07 17:11:31 2012 -0700
3.2 +++ b/jitcraft/BytecodeCompiler.cpp Sat Jul 07 20:28:29 2012 -0700
3.3 @@ -21,6 +21,7 @@
3.4 #include "Modules.h"
3.5 #include "Types.h"
3.6 #include "Array.h"
3.7 +#include "Strings.h"
3.8 #include "Zone.h"
3.9 #include "Heap-inl.h"
3.10
4.1 --- a/jitcraft/FixedArray.h Sat Jul 07 17:11:31 2012 -0700
4.2 +++ b/jitcraft/FixedArray.h Sat Jul 07 20:28:29 2012 -0700
4.3 @@ -1,4 +1,5 @@
4.4 -/*
4.5 +/* vim: set ts=4 sw=4 tw=99 et
4.6 + *
4.7 * Copyright (C) 2012 David Anderson
4.8 *
4.9 * This file is part of JITCraft.
4.10 @@ -62,11 +63,6 @@
4.11 {
4.12 uint32 length_;
4.13
4.14 - private:
4.15 - Object **vec() {
4.16 - return reinterpret_cast<Object **>(this + 1);
4.17 - }
4.18 -
4.19 public:
4.20 static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
4.21
4.22 @@ -78,7 +74,7 @@
4.23 }
4.24
4.25 static size_t SizeFor(unsigned length) {
4.26 - return sizeof(FixedArray) + sizeof(uint8) * length;
4.27 + return Align(sizeof(ByteArray) + sizeof(uint8) * length, kObjectAlignment);
4.28 }
4.29
4.30 static inline ByteArray *cast(Object *obj) {
5.1 --- a/jitcraft/Handles.h Sat Jul 07 17:11:31 2012 -0700
5.2 +++ b/jitcraft/Handles.h Sat Jul 07 20:28:29 2012 -0700
5.3 @@ -112,6 +112,9 @@
5.4 Object * const *address() const {
5.5 return (Object * const *)&thing_;
5.6 }
5.7 + T **ref() {
5.8 + return &thing_;
5.9 + }
5.10 operator T *() {
5.11 return thing_;
5.12 }
6.1 --- a/jitcraft/HashTable.h Sat Jul 07 17:11:31 2012 -0700
6.2 +++ b/jitcraft/HashTable.h Sat Jul 07 20:28:29 2012 -0700
6.3 @@ -1,23 +1,28 @@
6.4 -// vim: set ts=4 sw=4 tw=99 et:
6.5 -//
6.6 -//
6.7 -// (C) Copyright 2010-2011 AlliedModders LLC
6.8 -//
6.9 -// Initial Author: David Anderson
6.10 -// Contributors:
6.11 -//
6.12 -//
6.13 -
6.14 +/*
6.15 + * Copyright (C) 2012 David Anderson
6.16 + *
6.17 + * This file is part of JITCraft.
6.18 + *
6.19 + * JITCraft is free software: you can redistribute it and/or modify it under
6.20 + * the terms of the GNU General Public License as published by the Free
6.21 + * Software Foundation, either version 3 of the License, or (at your option)
6.22 + * any later version.
6.23 + *
6.24 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
6.25 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.26 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6.27 + *
6.28 + * You should have received a copy of the GNU General Public License along with
6.29 + * JITCraft. If not, see http://www.gnu.org/licenses/.
6.30 + */
6.31 #ifndef _INCLUDE_KEIMA_HASHTABLE_H_
6.32 #define _INCLUDE_KEIMA_HASHTABLE_H_
6.33
6.34 #include <new>
6.35 #include <limits.h>
6.36 -#include "Object.h"
6.37 -#include "vm/Array.h"
6.38 -#include "Environment.h"
6.39 +#include "Utility.h"
6.40
6.41 -namespace ke {
6.42 +namespace jc {
6.43
6.44 template <typename T>
6.45 class HashTableEntry
6.46 @@ -38,9 +43,10 @@
6.47 }
6.48 void setRemoved() {
6.49 hash_ = kRemovedHash;
6.50 - destruct();
6.51 + t_ = T();
6.52 }
6.53 void construct() {
6.54 + hash_ = kFreeHash;
6.55 new (&t_) T();
6.56 }
6.57 void destruct() {
6.58 @@ -66,6 +72,8 @@
6.59 template <typename HashPolicy, typename AllocPolicy>
6.60 class HashTable : public AllocPolicy
6.61 {
6.62 + friend class iterator;
6.63 +
6.64 typedef typename HashPolicy::Payload Payload;
6.65 typedef HashTableEntry<Payload> Entry;
6.66
6.67 @@ -73,6 +81,7 @@
6.68 uint32 nelements_;
6.69 uint32 ndeleted_;
6.70 Entry *table_;
6.71 + uint32 minCapacity_;
6.72
6.73 private:
6.74 static const uint32 kMinCapacity = 16;
6.75 @@ -88,7 +97,7 @@
6.76 }
6.77
6.78 Entry *createTable(uint32 capacity) {
6.79 - KE_ASSERT(capacity <= kMaxCapacity);
6.80 + assert(capacity <= kMaxCapacity);
6.81
6.82 Entry *table = (Entry *)this->malloc(capacity * sizeof(Entry));
6.83 if (!table)
6.84 @@ -154,7 +163,7 @@
6.85 : hash_(hash),
6.86 capacity_(capacity)
6.87 {
6.88 - KE_ASSERT(IsPowerOfTwo(capacity_));
6.89 + assert(IsPowerOfTwo(capacity_));
6.90 }
6.91
6.92 uint32 entry() const {
6.93 @@ -176,11 +185,13 @@
6.94 }
6.95
6.96 bool shrink() {
6.97 + if ((capacity_ >> 1) < minCapacity_)
6.98 + return true;
6.99 return changeCapacity(capacity_ >> 1);
6.100 }
6.101
6.102 bool grow() {
6.103 - KE_ASSERT(IsPowerOfTwo(kMaxCapacity));
6.104 + assert(IsPowerOfTwo(kMaxCapacity));
6.105 if (capacity_ >= kMaxCapacity) {
6.106 this->reportAllocationOverflow();
6.107 return false;
6.108 @@ -188,16 +199,8 @@
6.109 return changeCapacity(capacity_ << 1);
6.110 }
6.111
6.112 - bool checkDensity() {
6.113 - if (underloaded())
6.114 - return shrink();
6.115 - if (overloaded())
6.116 - return grow();
6.117 - return true;
6.118 - }
6.119 -
6.120 bool changeCapacity(uint32 newCapacity) {
6.121 - KE_ASSERT(newCapacity <= kMaxCapacity);
6.122 + assert(newCapacity <= kMaxCapacity);
6.123
6.124 Entry *newTable = createTable(newCapacity);
6.125 if (!newTable)
6.126 @@ -219,7 +222,7 @@
6.127 }
6.128 oldEntry.destruct();
6.129 }
6.130 - this->free(table_);
6.131 + this->free(oldTable);
6.132
6.133 return true;
6.134 }
6.135 @@ -277,7 +280,7 @@
6.136 }
6.137
6.138 bool add(Insert &i) {
6.139 - KE_ASSERT(!i.found());
6.140 + assert(!i.found());
6.141
6.142 // If the entry is deleted, just re-use the slot.
6.143 if (i.entry().removed()) {
6.144 @@ -310,13 +313,21 @@
6.145 return true;
6.146 }
6.147
6.148 + void remove(Entry &e) {
6.149 + assert(!e.isLive());
6.150 + e.setRemoved();
6.151 + ndeleted_++;
6.152 + nelements_--;
6.153 + }
6.154 +
6.155 public:
6.156 HashTable(AllocPolicy ap)
6.157 : AllocPolicy(ap),
6.158 capacity_(0),
6.159 nelements_(0),
6.160 ndeleted_(0),
6.161 - table_(NULL)
6.162 + table_(NULL),
6.163 + minCapacity_(kMinCapacity)
6.164 {
6.165 }
6.166
6.167 @@ -333,7 +344,9 @@
6.168 else if (capacity > kMaxCapacity)
6.169 capacity = kMaxCapacity;
6.170
6.171 - KE_ASSERT(IsPowerOfTwo(capacity));
6.172 + minCapacity_ = capacity;
6.173 +
6.174 + assert(IsPowerOfTwo(capacity));
6.175 capacity_ = capacity;
6.176
6.177 table_ = createTable(capacity_);
6.178 @@ -359,9 +372,52 @@
6.179 *i = payload;
6.180 return true;
6.181 }
6.182 +
6.183 + bool checkDensity() {
6.184 + if (underloaded())
6.185 + return shrink();
6.186 + if (overloaded())
6.187 + return grow();
6.188 + return true;
6.189 + }
6.190 +
6.191 + public:
6.192 + class iterator
6.193 + {
6.194 + HashTable *table_;
6.195 + Entry *i_;
6.196 + Entry *end_;
6.197 +
6.198 + public:
6.199 + iterator(HashTable *table)
6.200 + : table_(table),
6.201 + i_(table->table_),
6.202 + end_(table->table_ + table->capacity_)
6.203 + {
6.204 + while (i_ < end_ && !i_->isLive())
6.205 + i_++;
6.206 + }
6.207 +
6.208 + bool empty() const {
6.209 + return i_ == end_;
6.210 + }
6.211 +
6.212 + void erase() {
6.213 + assert(!empty());
6.214 + table_->remove(*i_);
6.215 + }
6.216 +
6.217 + const Payload &operator *() const {
6.218 + return i_->payload();
6.219 + }
6.220 +
6.221 + void next() {
6.222 + while (i_ < end_ && !i_->isLive())
6.223 + i_++;
6.224 + }
6.225 + };
6.226 };
6.227
6.228 }
6.229
6.230 #endif // _INCLUDE_KEIMA_HASHTABLE_H_
6.231 -
7.1 --- a/jitcraft/Heap.cpp Sat Jul 07 17:11:31 2012 -0700
7.2 +++ b/jitcraft/Heap.cpp Sat Jul 07 20:28:29 2012 -0700
7.3 @@ -22,6 +22,7 @@
7.4 #include "VirtualObjectVisitor.h"
7.5 #include "ObjectVisitor.h"
7.6 #include "Zone.h"
7.7 +#include "StringPool.h"
7.8
7.9 using namespace jc;
7.10
7.11 @@ -351,6 +352,9 @@
7.12 void
7.13 Heap::sweep()
7.14 {
7.15 + // Before destroying mark bits, sweep weak roots.
7.16 + zone_->symbols()->sweep();
7.17 +
7.18 // Note: we don't bother sweeping the LIFO space.
7.19 SweepOldSpace(&mapSpace_);
7.20 SweepOldSpace(&oldSpace_);
8.1 --- a/jitcraft/NameBinding.cpp Sat Jul 07 17:11:31 2012 -0700
8.2 +++ b/jitcraft/NameBinding.cpp Sat Jul 07 20:28:29 2012 -0700
8.3 @@ -16,11 +16,12 @@
8.4 * JITCraft. If not, see http://www.gnu.org/licenses/.
8.5 */
8.6 #include "NameBinding.h"
8.7 +#include "Strings.h"
8.8 #include "Zone.h"
8.9
8.10 using namespace jc;
8.11
8.12 -BoundName::BoundName(Scope *scope, Name *name, const SourcePosition &pos)
8.13 +BoundName::BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos)
8.14 : scope_(scope),
8.15 name_(name),
8.16 type_(NULL),
8.17 @@ -28,12 +29,12 @@
8.18 {
8.19 }
8.20
8.21 -NamedFunction::NamedFunction(Scope *scope, Name *name, const SourcePosition &pos)
8.22 +NamedFunction::NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos)
8.23 : BoundName(scope, name, pos)
8.24 {
8.25 }
8.26
8.27 -Variable::Variable(Scope *scope, Name *name, const SourcePosition &pos)
8.28 +Variable::Variable(Scope *scope, Handle<String> name, const SourcePosition &pos)
8.29 : BoundName(scope, name, pos),
8.30 location_(UNALLOCATED)
8.31 {
9.1 --- a/jitcraft/NameBinding.h Sat Jul 07 17:11:31 2012 -0700
9.2 +++ b/jitcraft/NameBinding.h Sat Jul 07 20:28:29 2012 -0700
9.3 @@ -19,7 +19,6 @@
9.4 #define _include_name_binding_h_
9.5
9.6 #include "PoolAllocator.h"
9.7 -#include "StringPool.h"
9.8 #include "Types.h"
9.9 #include "Scanner.h"
9.10
9.11 @@ -31,11 +30,12 @@
9.12 class Type;
9.13 class NamedEnum;
9.14 class NamedConstant;
9.15 +class String;
9.16
9.17 class BoundName : public PoolObject
9.18 {
9.19 Scope *scope_;
9.20 - Name *name_;
9.21 + ScopedRoot<String> name_;
9.22 ScopedRoot<Type> type_;
9.23 SourcePosition pos_;
9.24
9.25 @@ -47,11 +47,11 @@
9.26 CONSTANT
9.27 };
9.28
9.29 - BoundName(Scope *scope, Name *name, const SourcePosition &pos);
9.30 + BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos);
9.31
9.32 virtual Kind kind() const = 0;
9.33
9.34 - Name *name() const {
9.35 + String *name() const {
9.36 return name_;
9.37 }
9.38 Scope *scope() const {
9.39 @@ -85,7 +85,7 @@
9.40 unsigned slot_;
9.41
9.42 public:
9.43 - NamedFunction(Scope *scope, Name *name, const SourcePosition &pos);
9.44 + NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos);
9.45
9.46 Kind kind() const {
9.47 return FUNCTION;
9.48 @@ -101,7 +101,7 @@
9.49 class NamedEnum : public BoundName
9.50 {
9.51 public:
9.52 - NamedEnum(Scope *scope, Name *name, const SourcePosition &pos)
9.53 + NamedEnum(Scope *scope, Handle<String> name, const SourcePosition &pos)
9.54 : BoundName(scope, name, pos)
9.55 {
9.56 }
9.57 @@ -117,7 +117,7 @@
9.58 Type *type_;
9.59
9.60 public:
9.61 - NamedConstant(Scope *scope, Name *name, const SourcePosition &pos)
9.62 + NamedConstant(Scope *scope, Handle<String> name, const SourcePosition &pos)
9.63 : BoundName(scope, name, pos),
9.64 type_(NULL)
9.65 {
9.66 @@ -147,7 +147,7 @@
9.67 PARAMETER
9.68 };
9.69
9.70 - Variable(Scope *scope, Name *name, const SourcePosition &pos);
9.71 + Variable(Scope *scope, Handle<String> name, const SourcePosition &pos);
9.72
9.73 Kind kind() const {
9.74 return VARIABLE;
10.1 --- a/jitcraft/ObjectVisitor.h Sat Jul 07 17:11:31 2012 -0700
10.2 +++ b/jitcraft/ObjectVisitor.h Sat Jul 07 20:28:29 2012 -0700
10.3 @@ -27,6 +27,7 @@
10.4 #include "Modules.h"
10.5 #include "Functions.h"
10.6 #include "Array.h"
10.7 +#include "Strings.h"
10.8
10.9 namespace jc {
10.10
10.11 @@ -45,6 +46,7 @@
10.12 visitField(obj, Type::offsetOfContained());
10.13 visitField(obj, Type::offsetOfReturnType());
10.14 visitField(obj, Type::offsetOfParameters());
10.15 + visitField(obj, Type::offsetOfTag());
10.16 return sizeof(Type);
10.17 }
10.18
10.19 @@ -86,6 +88,10 @@
10.20 return sizeof(Function);
10.21 }
10.22
10.23 + size_t iterateString(Object *obj) {
10.24 + return String::SizeFor(String::cast(obj)->length());
10.25 + }
10.26 +
10.27 size_t iterateArray(Array *array, ArrayMap *map) {
10.28 if (map->type()->isArray()) {
10.29 unsigned length = array->nelements();
10.30 @@ -117,7 +123,7 @@
10.31 return iterateFixedArray(FixedArray::cast(obj));
10.32
10.33 case MapKind_ByteArray:
10.34 - return Align(iterateByteArray(ByteArray::cast(obj)), kObjectAlignment);
10.35 + return iterateByteArray(ByteArray::cast(obj));
10.36
10.37 case MapKind_Code:
10.38 return iterateCode(obj);
10.39 @@ -131,6 +137,9 @@
10.40 case MapKind_Function:
10.41 return iterateFunction(obj);
10.42
10.43 + case MapKind_String:
10.44 + return iterateString(obj);
10.45 +
10.46 case MapKind_Array:
10.47 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
10.48
10.49 @@ -155,7 +164,7 @@
10.50 return FixedArray::SizeFor(FixedArray::cast(obj)->length());
10.51
10.52 case MapKind_ByteArray:
10.53 - return Align(ByteArray::SizeFor(ByteArray::cast(obj)->length()), kObjectAlignment);
10.54 + return ByteArray::SizeFor(ByteArray::cast(obj)->length());
10.55
10.56 case MapKind_Code:
10.57 return sizeof(Code);
10.58 @@ -169,6 +178,9 @@
10.59 case MapKind_Function:
10.60 return sizeof(Function);
10.61
10.62 + case MapKind_String:
10.63 + return String::SizeFor(String::cast(obj)->length());
10.64 +
10.65 case MapKind_Array:
10.66 return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
10.67
11.1 --- a/jitcraft/Objects.h Sat Jul 07 17:11:31 2012 -0700
11.2 +++ b/jitcraft/Objects.h Sat Jul 07 20:28:29 2012 -0700
11.3 @@ -45,6 +45,7 @@
11.4 MapKind_Reference,
11.5 MapKind_Module,
11.6 MapKind_Function,
11.7 + MapKind_String,
11.8 MapKind_FreeRegion, // Special map denoting freed space.
11.9
11.10 // Used to represent Arrays. This does not have a canonical map.
12.1 --- a/jitcraft/Opcodes.cpp Sat Jul 07 17:11:31 2012 -0700
12.2 +++ b/jitcraft/Opcodes.cpp Sat Jul 07 20:28:29 2012 -0700
12.3 @@ -16,11 +16,13 @@
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 <stdlib.h>
12.8 #include "Opcodes.h"
12.9 #include "Utility.h"
12.10 #include "Code.h"
12.11 #include "Zone.h"
12.12 #include "Array.h"
12.13 +#include "Strings.h"
12.14 #include "Heap-inl.h"
12.15
12.16 using namespace jc;
12.17 @@ -186,7 +188,7 @@
12.18 {
12.19 ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
12.20 fprintf(fp, "%s:", map->type()->innermost()->tag()
12.21 - ? map->type()->innermost()->tag()
12.22 + ? map->type()->innermost()->tag()->chars()
12.23 : "_");
12.24 for (; map; map = map->contained()) {
12.25 Type *type = map->type();
13.1 --- a/jitcraft/Parser.cpp Sat Jul 07 17:11:31 2012 -0700
13.2 +++ b/jitcraft/Parser.cpp Sat Jul 07 20:28:29 2012 -0700
13.3 @@ -20,14 +20,15 @@
13.4 #include "Parser.h"
13.5 #include "FixedArray.h"
13.6 #include "Heap.h"
13.7 +#include "Strings.h"
13.8 #include "Heap-inl.h"
13.9
13.10 using namespace jc;
13.11
13.12 -Parser::Parser(CompileContext &cc, const char *stream, size_t length)
13.13 - : cc_(cc),
13.14 - pool_(ZONE()->pool()),
13.15 - strings_(pool_),
13.16 +Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
13.17 + : zone_(zone),
13.18 + cc_(cc),
13.19 + pool_(zone_->pool()),
13.20 scanner_(cc, stream, length),
13.21 scope_(NULL),
13.22 unbound_(NULL)
13.23 @@ -64,7 +65,7 @@
13.24 }
13.25
13.26 NameProxy *
13.27 -Parser::bind(Name *name)
13.28 +Parser::bind(Handle<String> name)
13.29 {
13.30 BoundName *bound = scope_->lookup(name);
13.31 NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
13.32 @@ -74,22 +75,22 @@
13.33 }
13.34
13.35 bool
13.36 -Parser::matchName(Name **name, TokenKind kind)
13.37 +Parser::matchName(String **name, TokenKind kind)
13.38 {
13.39 assert(kind == TOK_NAME || kind == TOK_LABEL);
13.40 *name = NULL;
13.41 if (!match(kind))
13.42 return false;
13.43 - *name = strings_.add(scanner_.literal());
13.44 + *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
13.45 return true;
13.46 }
13.47
13.48 -Name *
13.49 +String *
13.50 Parser::expectName()
13.51 {
13.52 if (!expect(TOK_NAME))
13.53 return NULL;
13.54 - return strings_.add(scanner_.literal());
13.55 + return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
13.56 }
13.57
13.58 void
13.59 @@ -105,8 +106,9 @@
13.60 switch (kind) {
13.61 case TOK_NAME:
13.62 {
13.63 - scanner_.scan();
13.64 - Name *name = strings_.add(scanner_.literal());
13.65 + Local<String> name(zone_, expectName());
13.66 + if (!name)
13.67 + return NULL;
13.68 return bind(name);
13.69 }
13.70
13.71 @@ -127,10 +129,10 @@
13.72 case TOK_STRING_LITERAL:
13.73 {
13.74 scanner_.scan();
13.75 - Local<ByteArray> array(ZONE(), ByteArray::New(ZONE(), scanner_.literal_length()));
13.76 + Local<ByteArray> array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1));
13.77 if (!array)
13.78 return NULL;
13.79 - memcpy(array->raw(), scanner_.literal(), scanner_.literal_length());
13.80 + memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1);
13.81 return new (pool_) StringLiteral(scanner_.begin(), array);
13.82 }
13.83
13.84 @@ -562,11 +564,11 @@
13.85 if (!expect(TOK_NEW))
13.86 return NULL;
13.87
13.88 - Name *tag;
13.89 - if (matchName(&tag, TOK_LABEL) && !tag)
13.90 + Local<String> tag(zone_);
13.91 + if (matchName(tag.ref(), TOK_LABEL) && !tag)
13.92 return NULL;
13.93
13.94 - Name *name = expectName();
13.95 + Local<String> name(zone_, expectName());
13.96 if (!name)
13.97 return NULL;
13.98
13.99 @@ -785,9 +787,9 @@
13.100
13.101 SourcePosition pos = scanner_.begin();
13.102
13.103 - Name *name = NULL;
13.104 - if (match(TOK_NAME)) {
13.105 - if ((name = strings_.add(scanner_.literal())) == NULL)
13.106 + Local<String> name(zone_);
13.107 + if (matchName(name.ref())) {
13.108 + if (!name)
13.109 return NULL;
13.110
13.111 if (BoundName *other = scope_->localLookup(name)) {
13.112 @@ -808,7 +810,7 @@
13.113 if (scanner_.peek() == TOK_RBRACE)
13.114 break;
13.115
13.116 - Name *name = expectName();
13.117 + Local<String> name(zone_, expectName());
13.118 if (!name)
13.119 return NULL;
13.120
13.121 @@ -838,7 +840,7 @@
13.122 Statement *
13.123 Parser::function()
13.124 {
13.125 - Name *name = expectName();
13.126 + Local<String> name(zone_, expectName());
13.127 if (!name)
13.128 return NULL;
13.129
13.130 @@ -867,7 +869,7 @@
13.131 while (true) {
13.132 bool ref = match(TOK_AMPERSAND);
13.133
13.134 - Name *name = expectName();
13.135 + Local<String> name(zone_, expectName());
13.136 if (!name)
13.137 return NULL;
13.138
13.139 @@ -879,7 +881,8 @@
13.140 if (!arg)
13.141 return NULL;
13.142
13.143 - Parameter *parameter = new (pool_) Parameter(arg, NULL, ref);
13.144 + Local<String> tag(zone_);
13.145 + Parameter *parameter = new (pool_) Parameter(arg, tag, ref);
13.146 parameters->push_back(parameter);
13.147
13.148 if (!match(TOK_COMMA))
13.149 @@ -966,7 +969,7 @@
13.150
13.151 void visit(NameProxy *name) {
13.152 prefix();
13.153 - fprintf(fp_, "[ NameProxy (%s)%s\n", name->name(),
13.154 + fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
13.155 (name->binding() ? "" : " unbound"));
13.156 }
13.157 void visit(CallExpression *node) {
13.158 @@ -980,7 +983,7 @@
13.159 }
13.160 void visit(FunctionStatement *node) {
13.161 prefix();
13.162 - fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name());
13.163 + fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
13.164 indent();
13.165 node->body()->accept(this);
13.166 unindent();
13.167 @@ -1038,7 +1041,7 @@
13.168 }
13.169 void visit(VariableDeclaration *node) {
13.170 prefix();
13.171 - fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name());
13.172 + fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
13.173 indent();
13.174 if (node->initialization())
13.175 node->initialization()->accept(this);
13.176 @@ -1071,11 +1074,11 @@
13.177 }
13.178 void visit(EnumStatement *node) {
13.179 prefix();
13.180 - fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
13.181 + fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
13.182 indent();
13.183 for (size_t i = 0; i < node->entries()->size(); i++) {
13.184 prefix();
13.185 - fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
13.186 + fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
13.187 if (node->entries()->at(i).expr) {
13.188 indent();
13.189 node->entries()->at(i).expr->accept(this);
14.1 --- a/jitcraft/Parser.h Sat Jul 07 17:11:31 2012 -0700
14.2 +++ b/jitcraft/Parser.h Sat Jul 07 20:28:29 2012 -0700
14.3 @@ -21,17 +21,17 @@
14.4 #include <stdio.h>
14.5 #include <vector>
14.6 #include "AST.h"
14.7 -#include "StringPool.h"
14.8 #include "Scanner.h"
14.9 #include "Scopes.h"
14.10 +#include "Strings.h"
14.11
14.12 namespace jc {
14.13
14.14 class Parser
14.15 {
14.16 + Zone *zone_;
14.17 CompileContext &cc_;
14.18 PoolAllocator &pool_;
14.19 - StringPool strings_;
14.20 Scanner scanner_;
14.21 Scope *scope_;
14.22 std::vector<NameProxy *> *unbound_;
14.23 @@ -44,9 +44,9 @@
14.24 Scope *enterScope(Scope::Kind kind);
14.25
14.26 VariableDeclaration *variableDeclaration();
14.27 - bool matchName(Name **name, TokenKind kind = TOK_NAME);
14.28 - Name *expectName();
14.29 - NameProxy *bind(Name *name);
14.30 + bool matchName(String **name, TokenKind kind = TOK_NAME);
14.31 + String *expectName();
14.32 + NameProxy *bind(Handle<String> name);
14.33 Expression *primitive();
14.34 Expression *call(Expression *callee);
14.35 Expression *index(Expression *left);
14.36 @@ -77,7 +77,7 @@
14.37 Statement *returnStatement();
14.38
14.39 public:
14.40 - Parser(CompileContext &cc, const char *stream, size_t length);
14.41 + Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
14.42
14.43 ParseTree *parse();
14.44 };
15.1 --- a/jitcraft/Scanner.h Sat Jul 07 17:11:31 2012 -0700
15.2 +++ b/jitcraft/Scanner.h Sat Jul 07 20:28:29 2012 -0700
15.3 @@ -72,7 +72,7 @@
15.4 return literal_.c_str();
15.5 }
15.6 size_t literal_length() const {
15.7 - return literal_.size() + 1;
15.8 + return literal_.size();
15.9 }
15.10 };
15.11
16.1 --- a/jitcraft/Scopes.cpp Sat Jul 07 17:11:31 2012 -0700
16.2 +++ b/jitcraft/Scopes.cpp Sat Jul 07 20:28:29 2012 -0700
16.3 @@ -20,6 +20,7 @@
16.4 #include "Zone.h"
16.5 #include "Types.h"
16.6 #include "TypeManager.h"
16.7 +#include "Strings.h"
16.8
16.9 using namespace jc;
16.10
16.11 @@ -65,7 +66,7 @@
16.12 }
16.13
16.14 BoundName *
16.15 -Scope::localLookup(Name *name)
16.16 +Scope::localLookup(Handle<String> name)
16.17 {
16.18 for (size_t i = 0; i < names_.size(); i++) {
16.19 if (names_[i]->name() == name)
16.20 @@ -75,7 +76,7 @@
16.21 }
16.22
16.23 BoundName *
16.24 -Scope::lookup(Name *name)
16.25 +Scope::lookup(Handle<String> name)
16.26 {
16.27 for (Scope *scope = this; scope; scope = scope->enclosing()) {
16.28 if (BoundName *bound = scope->localLookup(name))
16.29 @@ -85,7 +86,7 @@
16.30 }
16.31
16.32 Variable *
16.33 -Scope::declareVariable(Name *name, const SourcePosition &pos)
16.34 +Scope::declareVariable(Handle<String> name, const SourcePosition &pos)
16.35 {
16.36 assert(!localLookup(name));
16.37
16.38 @@ -95,7 +96,7 @@
16.39 }
16.40
16.41 Variable *
16.42 -Scope::declareArgument(Name *name, const SourcePosition &pos)
16.43 +Scope::declareArgument(Handle<String> name, const SourcePosition &pos)
16.44 {
16.45 assert(kind() == FUNCTION);
16.46 Variable *var = declareVariable(name, pos);
16.47 @@ -105,7 +106,7 @@
16.48 }
16.49
16.50 NamedFunction *
16.51 -Scope::declareFunction(Name *name, const SourcePosition &pos)
16.52 +Scope::declareFunction(Handle<String> name, const SourcePosition &pos)
16.53 {
16.54 assert(!localLookup(name));
16.55 assert(kind() == GLOBAL);
16.56 @@ -116,7 +117,7 @@
16.57 }
16.58
16.59 NamedEnum *
16.60 -Scope::declareEnum(Name *name, const SourcePosition &pos)
16.61 +Scope::declareEnum(Handle<String> name, const SourcePosition &pos)
16.62 {
16.63 NamedEnum *e = new (pool_) NamedEnum(this, name, pos);
16.64 names_.push_back(e);
16.65 @@ -124,7 +125,7 @@
16.66 }
16.67
16.68 NamedConstant *
16.69 -Scope::declareConstant(Name *name, const SourcePosition &pos)
16.70 +Scope::declareConstant(Handle<String> name, const SourcePosition &pos)
16.71 {
16.72 NamedConstant *constant = new (pool_) NamedConstant(this, name, pos);
16.73 names_.push_back(constant);
16.74 @@ -190,15 +191,17 @@
16.75 bool
16.76 Scope::Bind(ParseTree *tree)
16.77 {
16.78 + Local<String> name(ZONE());
16.79 for (size_t i = 0; i < tree->unbound()->size(); i++) {
16.80 NameProxy *proxy = tree->unbound()->at(i);
16.81 - BoundName *name = tree->scope()->lookup(proxy->name());
16.82 - if (!name) {
16.83 + name = proxy->name();
16.84 + BoundName *binding = tree->scope()->lookup(name);
16.85 + if (!binding) {
16.86 assert(false);
16.87 return false;
16.88 }
16.89
16.90 - proxy->bind(name);
16.91 + proxy->bind(binding);
16.92 }
16.93 return true;
16.94 }
16.95 @@ -227,6 +230,7 @@
16.96 if (!type)
16.97 return;
16.98
16.99 - lifoSlot_ = new (pool_) Variable(this, NULL, SourcePosition());
16.100 + Local<String> name(ZONE());
16.101 + lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
16.102 lifoSlot_->setType(type);
16.103 }
17.1 --- a/jitcraft/Scopes.h Sat Jul 07 17:11:31 2012 -0700
17.2 +++ b/jitcraft/Scopes.h Sat Jul 07 20:28:29 2012 -0700
17.3 @@ -79,14 +79,14 @@
17.4 void setUsesLifoHeap();
17.5
17.6 Scope *unlinkIfEmpty();
17.7 - BoundName *localLookup(Name *name);
17.8 - BoundName *lookup(Name *name);
17.9 + BoundName *localLookup(Handle<String> name);
17.10 + BoundName *lookup(Handle<String> name);
17.11
17.12 - NamedFunction *declareFunction(Name *name, const SourcePosition &pos);
17.13 - Variable *declareVariable(Name *name, const SourcePosition &pos);
17.14 - Variable *declareArgument(Name *name, const SourcePosition &pos);
17.15 - NamedEnum *declareEnum(Name *name, const SourcePosition &pos);
17.16 - NamedConstant *declareConstant(Name *name, const SourcePosition &pos);
17.17 + NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos);
17.18 + Variable *declareVariable(Handle<String> name, const SourcePosition &pos);
17.19 + Variable *declareArgument(Handle<String> name, const SourcePosition &pos);
17.20 + NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
17.21 + NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
17.22
17.23 void allocate(Variable *var);
17.24 void allocate();
18.1 --- a/jitcraft/SemanticAnalysis.cpp Sat Jul 07 17:11:31 2012 -0700
18.2 +++ b/jitcraft/SemanticAnalysis.cpp Sat Jul 07 20:28:29 2012 -0700
18.3 @@ -22,6 +22,7 @@
18.4 #include "TypeManager.h"
18.5 #include "Scopes.h"
18.6 #include "Heap-inl.h"
18.7 +#include "Strings.h"
18.8
18.9 using namespace jc;
18.10
18.11 @@ -158,6 +159,7 @@
18.12 return expression->type();
18.13 }
18.14
18.15 +// :TODO: this leaks an interior pointer.
18.16 static inline const char *
18.17 GetTypeName(Type *type)
18.18 {
18.19 @@ -168,7 +170,7 @@
18.20 if (type->isReference())
18.21 type = type->contained();
18.22 if (type->tag())
18.23 - return type->tag();
18.24 + return type->tag()->chars();
18.25 return "int";
18.26 }
18.27
18.28 @@ -388,7 +390,8 @@
18.29 void
18.30 SemanticAnalysis::visit(VariableDeclaration *node)
18.31 {
18.32 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(node->tag()));
18.33 + Local<String> tag(zone_, node->tag());
18.34 + Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
18.35 if (!type)
18.36 return;
18.37
18.38 @@ -528,7 +531,8 @@
18.39 for (size_t i = 0; i < node->parameters()->size(); i++) {
18.40 Parameter *parameter = node->parameters()->at(i);
18.41
18.42 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(parameter->tag()));
18.43 + Local<String> tag(zone_, parameter->tag());
18.44 + Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
18.45 if (!type)
18.46 return false;
18.47
18.48 @@ -617,8 +621,9 @@
18.49 }
18.50
18.51 if (given->primitive() != actual->primitive()) {
18.52 - const char *givenTag = given->tag() ? given->tag() : "_";
18.53 - const char *actualTag = given->tag() ? given->tag() : "_";
18.54 + // :TODO: leaks an interior pointer.
18.55 + const char *givenTag = given->tag() ? given->tag()->chars() : "_";
18.56 + const char *actualTag = given->tag() ? given->tag()->chars() : "_";
18.57 cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
18.58 return false;
18.59 }
18.60 @@ -652,8 +657,9 @@
18.61 }
18.62
18.63 if (given->primitive() != actual->primitive()) {
18.64 - const char *givenTag = given->tag() ? given->tag() : "_";
18.65 - const char *actualTag = given->tag() ? given->tag() : "_";
18.66 + // :TODO: leaks an interior pointer
18.67 + const char *givenTag = given->tag() ? given->tag()->chars() : "_";
18.68 + const char *actualTag = given->tag() ? given->tag()->chars() : "_";
18.69 cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
18.70 return false;
18.71 }
18.72 @@ -746,11 +752,11 @@
18.73 SemanticAnalysis::visit(EnumStatement *node)
18.74 {
18.75 // Forbid the blessed types.
18.76 - Name *tag = node->name();
18.77 - if (!strcmp(tag, "Float") ||
18.78 - !strcmp(tag, "String") ||
18.79 - !strcmp(tag, "any") ||
18.80 - !strcmp(tag, "bool"))
18.81 + Local<String> tag(zone_, node->name());
18.82 + if (!strcmp(tag->chars(), "Float") ||
18.83 + !strcmp(tag->chars(), "String") ||
18.84 + !strcmp(tag->chars(), "any") ||
18.85 + !strcmp(tag->chars(), "bool"))
18.86 {
18.87 cc_.reportError(node->pos(), Message_InvalidEnumName);
18.88 return;
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/jitcraft/StringPool.cpp Sat Jul 07 20:28:29 2012 -0700
19.3 @@ -0,0 +1,69 @@
19.4 +/*
19.5 + * Copyright (C) 2012 David Anderson
19.6 + *
19.7 + * This file is part of JITCraft.
19.8 + *
19.9 + * JITCraft is free software: you can redistribute it and/or modify it under
19.10 + * the terms of the GNU General Public License as published by the Free
19.11 + * Software Foundation, either version 3 of the License, or (at your option)
19.12 + * any later version.
19.13 + *
19.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
19.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19.17 + *
19.18 + * You should have received a copy of the GNU General Public License along with
19.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
19.20 + */
19.21 +#include "StringPool.h"
19.22 +#include "Strings.h"
19.23 +#include "Spaces.h"
19.24 +
19.25 +using namespace jc;
19.26 +
19.27 +StringPool::StringPool(Zone *zone)
19.28 + : zone_(zone),
19.29 + set_(ZoneAllocatorPolicy())
19.30 +{
19.31 +}
19.32 +
19.33 +StringPool::~StringPool()
19.34 +{
19.35 +}
19.36 +
19.37 +bool
19.38 +StringPool::initialize()
19.39 +{
19.40 + if (!set_.init(32))
19.41 + return false;
19.42 + return true;
19.43 +}
19.44 +
19.45 +String *
19.46 +StringPool::add(const char *str, size_t length)
19.47 +{
19.48 + StringSet::Insert i = set_.findForAdd(CharsAndLength(str, length));
19.49 + if (i.found())
19.50 + return *i;
19.51 +
19.52 + String *obj = String::New(zone_, str, length, Heap::Tenure_Old);
19.53 + if (!obj)
19.54 + return NULL;
19.55 +
19.56 + set_.add(i, obj);
19.57 + return obj;
19.58 +}
19.59 +
19.60 +void
19.61 +StringPool::sweep()
19.62 +{
19.63 + for (StringSet::iterator i(&set_); !i.empty(); i.next()) {
19.64 + String *obj = *i;
19.65 + MarkBit bits = HeapChunk::GetMarkBit(obj);
19.66 + if (HeapChunk::IsWhite(bits))
19.67 + i.erase();
19.68 + else
19.69 + assert(HeapChunk::IsBlack(bits));
19.70 + }
19.71 + set_.checkDensity();
19.72 +}
20.1 --- a/jitcraft/StringPool.h Sat Jul 07 17:11:31 2012 -0700
20.2 +++ b/jitcraft/StringPool.h Sat Jul 07 20:28:29 2012 -0700
20.3 @@ -18,37 +18,66 @@
20.4 #ifndef _include_jitcraft_string_pool_h_
20.5 #define _include_jitcraft_string_pool_h_
20.6
20.7 -#include <vector>
20.8 -#include <string.h>
20.9 -#include "PoolAllocator.h"
20.10 +#include "AllocatorPolicies.h"
20.11 +#include "HashTable.h"
20.12 +#include "Strings.h"
20.13
20.14 namespace jc {
20.15
20.16 -typedef const char Name;
20.17 +class Zone;
20.18 +class String;
20.19
20.20 -// Guarantee that strings with the same contents will map to one pointer. The
20.21 -// strings are pool allocated, and search is linear for simplicity.
20.22 +// Guarantee that strings with the same contents will map to one pointer.
20.23 class StringPool
20.24 {
20.25 - PoolAllocator &pool_;
20.26 - std::vector<Name *> strings_;
20.27 + class CharsAndLength {
20.28 + const char *str_;
20.29 + size_t length_;
20.30 +
20.31 + public:
20.32 + CharsAndLength(const char *str, size_t length)
20.33 + : str_(str),
20.34 + length_(length)
20.35 + {
20.36 + }
20.37 +
20.38 + const char *str() const {
20.39 + return str_;
20.40 + }
20.41 + size_t length() const {
20.42 + return length_;
20.43 + }
20.44 + };
20.45 +
20.46 + struct Policy
20.47 + {
20.48 + typedef String * Payload;
20.49 +
20.50 + static uint32 hash(const CharsAndLength &key) {
20.51 + return HashCharSequence(key.str(), key.length());
20.52 + }
20.53 +
20.54 + static bool matches(const CharsAndLength &key, String *string) {
20.55 + if (string->length() != key.length())
20.56 + return false;
20.57 + return memcmp(string->chars(), key.str(), key.length() * sizeof(char)) == 0;
20.58 + }
20.59 + };
20.60 +
20.61 + typedef HashTable<Policy, ZoneAllocatorPolicy> StringSet;
20.62
20.63 public:
20.64 - StringPool(PoolAllocator &pool)
20.65 - : pool_(pool)
20.66 - {
20.67 - }
20.68 + StringPool(Zone *zone);
20.69 + ~StringPool();
20.70 + bool initialize();
20.71
20.72 - Name *add(const char *string) {
20.73 - for (size_t i = 0; i < strings_.size(); i++) {
20.74 - if (strcmp(strings_[i], string) == 0)
20.75 - return strings_[i];
20.76 - }
20.77 - char *name = (char *)pool_.allocate(strlen(string) + 1);
20.78 - strcpy(name, string);
20.79 - strings_.push_back(name);
20.80 - return name;
20.81 - }
20.82 + public:
20.83 + String *add(const char *str, size_t len);
20.84 + void sweep();
20.85 +
20.86 + private:
20.87 + Zone *zone_;
20.88 + StringSet set_;
20.89 };
20.90
20.91 }
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/jitcraft/Strings.cpp Sat Jul 07 20:28:29 2012 -0700
21.3 @@ -0,0 +1,43 @@
21.4 +/* vim: set ts=4 sw=4 tw=99 et:
21.5 + *
21.6 + * Copyright (C) 2012 David Anderson
21.7 + *
21.8 + * This file is part of JITCraft.
21.9 + *
21.10 + * JITCraft is free software: you can redistribute it and/or modify it under
21.11 + * the terms of the GNU General Public License as published by the Free
21.12 + * Software Foundation, either version 3 of the License, or (at your option)
21.13 + * any later version.
21.14 + *
21.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
21.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
21.18 + *
21.19 + * You should have received a copy of the GNU General Public License along with
21.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
21.21 + */
21.22 +#include "Strings.h"
21.23 +#include "Zone.h"
21.24 +#include "Heap-inl.h"
21.25 +
21.26 +using namespace jc;
21.27 +
21.28 +String *
21.29 +String::New(Zone *zone, const char *from, Heap::Tenure tenure)
21.30 +{
21.31 + return New(zone, from, strlen(from), tenure);
21.32 +}
21.33 +
21.34 +String *
21.35 +String::New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure)
21.36 +{
21.37 + size_t bytes = SizeFor(length);
21.38 + Local<String> string(zone, String::cast(zone->allocate(MapKind_String, bytes, tenure)));
21.39 + if (!string)
21.40 + return NULL;
21.41 +
21.42 + string->length_ = length;
21.43 + memcpy(string->chars(), from, length + 1);
21.44 +
21.45 + return string;
21.46 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/jitcraft/Strings.h Sat Jul 07 20:28:29 2012 -0700
22.3 @@ -0,0 +1,54 @@
22.4 +/* vim: set ts=4 sw=4 tw=99 et:
22.5 + *
22.6 + * Copyright (C) 2012 David Anderson
22.7 + *
22.8 + * This file is part of JITCraft.
22.9 + *
22.10 + * JITCraft is free software: you can redistribute it and/or modify it under
22.11 + * the terms of the GNU General Public License as published by the Free
22.12 + * Software Foundation, either version 3 of the License, or (at your option)
22.13 + * any later version.
22.14 + *
22.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
22.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22.18 + *
22.19 + * You should have received a copy of the GNU General Public License along with
22.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
22.21 + */
22.22 +#ifndef _include_jitcraft_string_h_
22.23 +#define _include_jitcraft_string_h_
22.24 +
22.25 +#include "Heap.h"
22.26 +
22.27 +namespace jc {
22.28 +
22.29 +// A fixed-length string containing UTF-8 characters.
22.30 +class String : public Object
22.31 +{
22.32 + uint32 length_;
22.33 +
22.34 + public:
22.35 + static String *New(Zone *zone, const char *from, Heap::Tenure tenure = Heap::Tenure_Default);
22.36 + static String *New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure = Heap::Tenure_Default);
22.37 +
22.38 + unsigned length() {
22.39 + return length_;
22.40 + }
22.41 + char *chars() {
22.42 + return reinterpret_cast<char *>(this + 1);
22.43 + }
22.44 +
22.45 + static size_t SizeFor(unsigned length) {
22.46 + return Align(sizeof(String) + sizeof(char) * (length + 1), kObjectAlignment);
22.47 + }
22.48 +
22.49 + static inline String *cast(Object *obj) {
22.50 + assert(!obj || obj->is(MapKind_String));
22.51 + return reinterpret_cast<String *>(obj);
22.52 + }
22.53 +};
22.54 +
22.55 +}
22.56 +
22.57 +#endif // _include_jitcraft_string_h_
23.1 --- a/jitcraft/TypeManager.cpp Sat Jul 07 17:11:31 2012 -0700
23.2 +++ b/jitcraft/TypeManager.cpp Sat Jul 07 20:28:29 2012 -0700
23.3 @@ -19,6 +19,7 @@
23.4 #include "Types.h"
23.5 #include "TypeManager.h"
23.6 #include "Zone.h"
23.7 +#include "Strings.h"
23.8
23.9 using namespace jc;
23.10
23.11 @@ -31,13 +32,23 @@
23.12 bool
23.13 TypeManager::initialize()
23.14 {
23.15 - if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, NULL)) == NULL)
23.16 + Local<String> floatTag(zone_, zone_->makeSymbol("Float"));
23.17 + if (!floatTag)
23.18 + return false;
23.19 +
23.20 + Local<String> stringTag(zone_, zone_->makeSymbol("String"));
23.21 + if (!stringTag)
23.22 return false;
23.23 - if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, "Float")) == NULL)
23.24 +
23.25 + Local<String> nullTag(zone_);
23.26 +
23.27 + if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, nullTag)) == NULL)
23.28 + return false;
23.29 + if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, floatTag)) == NULL)
23.30 return false;
23.31 if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
23.32 return false;
23.33 - if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, "String")) == NULL)
23.34 + if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, stringTag)) == NULL)
23.35 return false;
23.36
23.37 Local<Type> type(zone_);
23.38 @@ -51,13 +62,13 @@
23.39 }
23.40
23.41 Type *
23.42 -TypeManager::getPrimitiveForTag(Name *tag)
23.43 +TypeManager::getPrimitiveForTag(Handle<String> tag)
23.44 {
23.45 - if (tag == NULL)
23.46 + if (!tag)
23.47 return getPrimitive(PrimitiveType_Int32);
23.48 - if (strcmp(tag, "Float") == 0)
23.49 + if (strcmp(tag->chars(), "Float") == 0)
23.50 return getPrimitive(PrimitiveType_Float);
23.51 - if (strcmp(tag, "String") == 0)
23.52 + if (strcmp(tag->chars(), "String") == 0)
23.53 return getPrimitive(PrimitiveType_Char);
23.54 return NULL;
23.55 }
24.1 --- a/jitcraft/TypeManager.h Sat Jul 07 17:11:31 2012 -0700
24.2 +++ b/jitcraft/TypeManager.h Sat Jul 07 20:28:29 2012 -0700
24.3 @@ -24,6 +24,8 @@
24.4
24.5 namespace jc {
24.6
24.7 +class String;
24.8 +
24.9 class TypeManager
24.10 {
24.11 Zone *zone_;
24.12 @@ -37,7 +39,7 @@
24.13
24.14 bool initialize();
24.15
24.16 - Type *getPrimitiveForTag(Name *tag);
24.17 + Type *getPrimitiveForTag(Handle<String>);
24.18 Type *getPrimitive(PrimitiveType type) {
24.19 return primitiveTypes_[type];
24.20 }
25.1 --- a/jitcraft/Types.cpp Sat Jul 07 17:11:31 2012 -0700
25.2 +++ b/jitcraft/Types.cpp Sat Jul 07 20:28:29 2012 -0700
25.3 @@ -17,12 +17,13 @@
25.4 */
25.5 #include "Types.h"
25.6 #include "Zone.h"
25.7 +#include "Strings.h"
25.8 #include "Heap-inl.h"
25.9
25.10 using namespace jc;
25.11
25.12 Type *
25.13 -Type::NewPrimitive(Zone *zone, Name *tag)
25.14 +Type::NewPrimitive(Zone *zone, Handle<String> tag)
25.15 {
25.16 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
25.17 if (!type)
25.18 @@ -34,9 +35,9 @@
25.19 type->returnType_ = NULL;
25.20 type->parameters_ = NULL;
25.21
25.22 - if (tag && strcmp(tag, "Float") == 0)
25.23 + if (tag && strcmp(tag->chars(), "Float") == 0)
25.24 type->primitive_ = PrimitiveType_Float;
25.25 - else if (tag && strcmp(tag, "String") == 0)
25.26 + else if (tag && strcmp(tag->chars(), "String") == 0)
25.27 type->primitive_ = PrimitiveType_Char;
25.28 else
25.29 type->primitive_ = PrimitiveType_Int32;
26.1 --- a/jitcraft/Types.h Sat Jul 07 17:11:31 2012 -0700
26.2 +++ b/jitcraft/Types.h Sat Jul 07 20:28:29 2012 -0700
26.3 @@ -19,13 +19,14 @@
26.4 #ifndef _include_jc_types_h_
26.5 #define _include_jc_types_h_
26.6
26.7 -#include "StringPool.h"
26.8 #include "Heap.h"
26.9 #include "Barriers.h"
26.10 #include "FixedArray.h"
26.11
26.12 namespace jc {
26.13
26.14 +class String;
26.15 +
26.16 enum PrimitiveType
26.17 {
26.18 PrimitiveType_Char, // signed, 8-bit character
26.19 @@ -53,7 +54,7 @@
26.20 static const int UNKNOWN_SIZE = -1;
26.21 static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
26.22
26.23 - static Type *NewPrimitive(Zone *zone, Name *tag);
26.24 + static Type *NewPrimitive(Zone *zone, Handle<String> tag);
26.25 static Type *NewPrimitive(Zone *zone, PrimitiveType type);
26.26 static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
26.27 static Type *NewReference(Zone *zone, Handle<Type> contained);
26.28 @@ -92,7 +93,7 @@
26.29 assert(isArray());
26.30 return levels_;
26.31 }
26.32 - Name *tag() {
26.33 + String *tag() {
26.34 assert(isPrimitive());
26.35 return tag_;
26.36 }
26.37 @@ -143,12 +144,15 @@
26.38 static inline size_t offsetOfParameters() {
26.39 return offsetof(Type, parameters_);
26.40 }
26.41 + static inline size_t offsetOfTag() {
26.42 + return offsetof(Type, tag_);
26.43 + }
26.44 // End GC Descriptor.
26.45
26.46 private:
26.47 Kind kind_;
26.48 PrimitiveType primitive_;
26.49 - Name *tag_;
26.50 + Barriered<String> tag_;
26.51
26.52 // Arrays only.
26.53 int32 elements_;
27.1 --- a/jitcraft/Utility.h Sat Jul 07 17:11:31 2012 -0700
27.2 +++ b/jitcraft/Utility.h Sat Jul 07 20:28:29 2012 -0700
27.3 @@ -70,6 +70,45 @@
27.4 }
27.5 };
27.6
27.7 +// Bob Jenkin's one-at-a-time hash function[1].
27.8 +//
27.9 +// [1] http://burtleburtle.net/bob/hash/doobs.html
27.10 +class CharacterStreamHasher
27.11 +{
27.12 + uint32 hash;
27.13 +
27.14 + public:
27.15 + CharacterStreamHasher()
27.16 + : hash(0)
27.17 + { }
27.18 +
27.19 + void add(char c) {
27.20 + hash += c;
27.21 + hash += (hash << 10);
27.22 + hash ^= (hash >> 6);
27.23 + }
27.24 +
27.25 + void add(const char *s, size_t length) {
27.26 + for (size_t i = 0; i < length; i++)
27.27 + add(s[i]);
27.28 + }
27.29 +
27.30 + uint32 result() {
27.31 + hash += (hash << 3);
27.32 + hash ^= (hash >> 11);
27.33 + hash += (hash << 15);
27.34 + return hash;
27.35 + }
27.36 +};
27.37 +
27.38 +static inline uint32
27.39 +HashCharSequence(const char *s, size_t length)
27.40 +{
27.41 + CharacterStreamHasher hasher;
27.42 + hasher.add(s, length);
27.43 + return hasher.result();
27.44 +}
27.45 +
27.46 static inline size_t
27.47 Log2(size_t number)
27.48 {
28.1 --- a/jitcraft/Zone.cpp Sat Jul 07 17:11:31 2012 -0700
28.2 +++ b/jitcraft/Zone.cpp Sat Jul 07 20:28:29 2012 -0700
28.3 @@ -17,7 +17,9 @@
28.4 * JITCraft. If not, see http://www.gnu.org/licenses/.
28.5 */
28.6 #include "Zone.h"
28.7 +#include "StringPool.h"
28.8 #include "TypeManager.h"
28.9 +#include "AllocatorPolicies.h"
28.10
28.11 using namespace jc;
28.12
28.13 @@ -30,6 +32,12 @@
28.14 {
28.15 }
28.16
28.17 +Zone::~Zone()
28.18 +{
28.19 + delete symbols_;
28.20 + delete types_;
28.21 +}
28.22 +
28.23 bool
28.24 Zone::initialize()
28.25 {
28.26 @@ -38,6 +46,10 @@
28.27 if (!heap_.initialize())
28.28 return false;
28.29
28.30 + symbols_ = new StringPool(this);
28.31 + if (!symbols_ || !symbols_->initialize())
28.32 + return false;
28.33 +
28.34 maps_[MapKind_Meta] = heap_.metaMap();
28.35 if ((maps_[MapKind_Type] = allocateMap(MapKind_Type, sizeof(Map))) == NULL)
28.36 return false;
28.37 @@ -55,6 +67,8 @@
28.38 return false;
28.39 if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
28.40 return false;
28.41 + if ((maps_[MapKind_String] = allocateMap(MapKind_String, sizeof(Map))) == NULL)
28.42 + return false;
28.43 if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
28.44 return false;
28.45
28.46 @@ -94,3 +108,28 @@
28.47 stack_.accept(visitor);
28.48 }
28.49
28.50 +String *
28.51 +Zone::makeSymbol(const char *str, size_t length)
28.52 +{
28.53 + return symbols_->add(str, length);
28.54 +}
28.55 +
28.56 +String *
28.57 +Zone::makeSymbol(const char *str)
28.58 +{
28.59 + return makeSymbol(str, strlen(str));
28.60 +}
28.61 +
28.62 +void
28.63 +ZoneAllocatorPolicy::reportOutOfMemory()
28.64 +{
28.65 + // :TODO: report
28.66 + assert(false);
28.67 +}
28.68 +
28.69 +void
28.70 +ZoneAllocatorPolicy::reportAllocationOverflow()
28.71 +{
28.72 + // :TODO: report
28.73 + assert(false);
28.74 +}
29.1 --- a/jitcraft/Zone.h Sat Jul 07 17:11:31 2012 -0700
29.2 +++ b/jitcraft/Zone.h Sat Jul 07 20:28:29 2012 -0700
29.3 @@ -30,6 +30,8 @@
29.4 namespace jc {
29.5
29.6 class TypeManager;
29.7 +class String;
29.8 +class StringPool;
29.9
29.10 class Zone
29.11 {
29.12 @@ -41,6 +43,7 @@
29.13 Unbarriered<Map> maps_[MapKinds_Total];
29.14
29.15 TypeManager *types_;
29.16 + StringPool *symbols_;
29.17
29.18 // Root list.
29.19 Local<Object> *lastLocalRoot_;
29.20 @@ -48,6 +51,7 @@
29.21
29.22 public:
29.23 Zone();
29.24 + ~Zone();
29.25 bool initialize();
29.26
29.27 PoolAllocator &pool() {
29.28 @@ -84,6 +88,12 @@
29.29 RootScopeManager &rootScopes() {
29.30 return rootScopes_;
29.31 }
29.32 + StringPool *symbols() {
29.33 + return symbols_;
29.34 + }
29.35 +
29.36 + String *makeSymbol(const char *string, size_t length);
29.37 + String *makeSymbol(const char *string);
29.38
29.39 void accept(VirtualObjectVisitor *visitor);
29.40 };
30.1 --- a/jitcraft/jitcraft.vcxproj Sat Jul 07 17:11:31 2012 -0700
30.2 +++ b/jitcraft/jitcraft.vcxproj Sat Jul 07 20:28:29 2012 -0700
30.3 @@ -98,11 +98,14 @@
30.4 <ClCompile Include="SemanticAnalysis.cpp" />
30.5 <ClCompile Include="Spaces.cpp" />
30.6 <ClCompile Include="Stack.cpp" />
30.7 + <ClCompile Include="StringPool.cpp" />
30.8 + <ClCompile Include="Strings.cpp" />
30.9 <ClCompile Include="TypeManager.cpp" />
30.10 <ClCompile Include="Types.cpp" />
30.11 <ClCompile Include="Zone.cpp" />
30.12 </ItemGroup>
30.13 <ItemGroup>
30.14 + <ClInclude Include="AllocatorPolicies.h" />
30.15 <ClInclude Include="Array.h" />
30.16 <ClInclude Include="AST.h" />
30.17 <ClInclude Include="Barriers.h" />
30.18 @@ -134,6 +137,7 @@
30.19 <ClInclude Include="Spaces-inl.h" />
30.20 <ClInclude Include="Spaces.h" />
30.21 <ClInclude Include="Stack.h" />
30.22 + <ClInclude Include="Strings.h" />
30.23 <ClInclude Include="StringPool.h" />
30.24 <ClInclude Include="TypeManager.h" />
30.25 <ClInclude Include="Types.h" />
31.1 --- a/jitcraft/main.cpp Sat Jul 07 17:11:31 2012 -0700
31.2 +++ b/jitcraft/main.cpp Sat Jul 07 20:28:29 2012 -0700
31.3 @@ -62,7 +62,7 @@
31.4 RootScope roots(ZONE());
31.5 CompileContext cc(ZONE());
31.6
31.7 - Parser parser(cc, stream, length);
31.8 + Parser parser(ZONE(), cc, stream, length);
31.9 ParseTree *tree = parser.parse();
31.10 if (!tree)
31.11 return false;