• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Copyright 2014 the V8 project authors. All rights reserved.
2  // Redistribution and use in source and binary forms, with or without
3  // modification, are permitted provided that the following conditions are
4  // met:
5  //
6  //     * Redistributions of source code must retain the above copyright
7  //       notice, this list of conditions and the following disclaimer.
8  //     * Redistributions in binary form must reproduce the above
9  //       copyright notice, this list of conditions and the following
10  //       disclaimer in the documentation and/or other materials provided
11  //       with the distribution.
12  //     * Neither the name of Google Inc. nor the names of its
13  //       contributors may be used to endorse or promote products derived
14  //       from this software without specific prior written permission.
15  //
16  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  
28  #include "src/ast-value-factory.h"
29  
30  #include "src/api.h"
31  #include "src/objects.h"
32  
33  namespace v8 {
34  namespace internal {
35  
36  namespace {
37  
38  // For using StringToArrayIndex.
39  class OneByteStringStream {
40   public:
OneByteStringStream(Vector<const byte> lb)41    explicit OneByteStringStream(Vector<const byte> lb) :
42        literal_bytes_(lb), pos_(0) {}
43  
HasMore()44    bool HasMore() { return pos_ < literal_bytes_.length(); }
GetNext()45    uint16_t GetNext() { return literal_bytes_[pos_++]; }
46  
47   private:
48    Vector<const byte> literal_bytes_;
49    int pos_;
50  };
51  
52  }
53  
54  class AstRawStringInternalizationKey : public HashTableKey {
55   public:
AstRawStringInternalizationKey(const AstRawString * string)56    explicit AstRawStringInternalizationKey(const AstRawString* string)
57        : string_(string) {}
58  
IsMatch(Object * other)59    virtual bool IsMatch(Object* other) OVERRIDE {
60      if (string_->is_one_byte_)
61        return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
62      return String::cast(other)->IsTwoByteEqualTo(
63          Vector<const uint16_t>::cast(string_->literal_bytes_));
64    }
65  
Hash()66    virtual uint32_t Hash() OVERRIDE {
67      return string_->hash() >> Name::kHashShift;
68    }
69  
HashForObject(Object * key)70    virtual uint32_t HashForObject(Object* key) OVERRIDE {
71      return String::cast(key)->Hash();
72    }
73  
AsHandle(Isolate * isolate)74    virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
75      if (string_->is_one_byte_)
76        return isolate->factory()->NewOneByteInternalizedString(
77            string_->literal_bytes_, string_->hash());
78      return isolate->factory()->NewTwoByteInternalizedString(
79          Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
80    }
81  
82   private:
83    const AstRawString* string_;
84  };
85  
86  
Internalize(Isolate * isolate)87  void AstRawString::Internalize(Isolate* isolate) {
88    if (!string_.is_null()) return;
89    if (literal_bytes_.length() == 0) {
90      string_ = isolate->factory()->empty_string();
91    } else {
92      AstRawStringInternalizationKey key(this);
93      string_ = StringTable::LookupKey(isolate, &key);
94    }
95  }
96  
97  
AsArrayIndex(uint32_t * index) const98  bool AstRawString::AsArrayIndex(uint32_t* index) const {
99    if (!string_.is_null())
100      return string_->AsArrayIndex(index);
101    if (!is_one_byte_ || literal_bytes_.length() == 0 ||
102        literal_bytes_.length() > String::kMaxArrayIndexSize)
103      return false;
104    OneByteStringStream stream(literal_bytes_);
105    return StringToArrayIndex(&stream, index);
106  }
107  
108  
IsOneByteEqualTo(const char * data) const109  bool AstRawString::IsOneByteEqualTo(const char* data) const {
110    int length = static_cast<int>(strlen(data));
111    if (is_one_byte_ && literal_bytes_.length() == length) {
112      const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
113      return !strncmp(token, data, length);
114    }
115    return false;
116  }
117  
118  
Compare(void * a,void * b)119  bool AstRawString::Compare(void* a, void* b) {
120    AstRawString* string1 = reinterpret_cast<AstRawString*>(a);
121    AstRawString* string2 = reinterpret_cast<AstRawString*>(b);
122    if (string1->is_one_byte_ != string2->is_one_byte_) return false;
123    if (string1->hash_ != string2->hash_) return false;
124    int length = string1->literal_bytes_.length();
125    if (string2->literal_bytes_.length() != length) return false;
126    return memcmp(string1->literal_bytes_.start(),
127                  string2->literal_bytes_.start(), length) == 0;
128  }
129  
130  
Internalize(Isolate * isolate)131  void AstConsString::Internalize(Isolate* isolate) {
132    // AstRawStrings are internalized before AstConsStrings so left and right are
133    // already internalized.
134    string_ = isolate->factory()
135                  ->NewConsString(left_->string(), right_->string())
136                  .ToHandleChecked();
137  }
138  
139  
IsPropertyName() const140  bool AstValue::IsPropertyName() const {
141    if (type_ == STRING) {
142      uint32_t index;
143      return !string_->AsArrayIndex(&index);
144    }
145    return false;
146  }
147  
148  
BooleanValue() const149  bool AstValue::BooleanValue() const {
150    switch (type_) {
151      case STRING:
152        DCHECK(string_ != NULL);
153        return !string_->IsEmpty();
154      case SYMBOL:
155        UNREACHABLE();
156        break;
157      case NUMBER:
158        return DoubleToBoolean(number_);
159      case SMI:
160        return smi_ != 0;
161      case STRING_ARRAY:
162        UNREACHABLE();
163        break;
164      case BOOLEAN:
165        return bool_;
166      case NULL_TYPE:
167        return false;
168      case THE_HOLE:
169        UNREACHABLE();
170        break;
171      case UNDEFINED:
172        return false;
173    }
174    UNREACHABLE();
175    return false;
176  }
177  
178  
Internalize(Isolate * isolate)179  void AstValue::Internalize(Isolate* isolate) {
180    switch (type_) {
181      case STRING:
182        DCHECK(string_ != NULL);
183        // Strings are already internalized.
184        DCHECK(!string_->string().is_null());
185        break;
186      case SYMBOL:
187        value_ = Object::GetProperty(
188                     isolate, handle(isolate->native_context()->builtins()),
189                     symbol_name_).ToHandleChecked();
190        break;
191      case NUMBER:
192        value_ = isolate->factory()->NewNumber(number_, TENURED);
193        break;
194      case SMI:
195        value_ = handle(Smi::FromInt(smi_), isolate);
196        break;
197      case BOOLEAN:
198        if (bool_) {
199          value_ = isolate->factory()->true_value();
200        } else {
201          value_ = isolate->factory()->false_value();
202        }
203        break;
204      case STRING_ARRAY: {
205        DCHECK(strings_ != NULL);
206        Factory* factory = isolate->factory();
207        int len = strings_->length();
208        Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
209        for (int i = 0; i < len; i++) {
210          const AstRawString* string = (*strings_)[i];
211          Handle<Object> element = string->string();
212          // Strings are already internalized.
213          DCHECK(!element.is_null());
214          elements->set(i, *element);
215        }
216        value_ =
217            factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
218        break;
219      }
220      case NULL_TYPE:
221        value_ = isolate->factory()->null_value();
222        break;
223      case THE_HOLE:
224        value_ = isolate->factory()->the_hole_value();
225        break;
226      case UNDEFINED:
227        value_ = isolate->factory()->undefined_value();
228        break;
229    }
230  }
231  
232  
GetOneByteString(Vector<const uint8_t> literal)233  const AstRawString* AstValueFactory::GetOneByteString(
234      Vector<const uint8_t> literal) {
235    uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
236        literal.start(), literal.length(), hash_seed_);
237    return GetString(hash, true, literal);
238  }
239  
240  
GetTwoByteString(Vector<const uint16_t> literal)241  const AstRawString* AstValueFactory::GetTwoByteString(
242      Vector<const uint16_t> literal) {
243    uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
244        literal.start(), literal.length(), hash_seed_);
245    return GetString(hash, false, Vector<const byte>::cast(literal));
246  }
247  
248  
GetString(Handle<String> literal)249  const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
250    DisallowHeapAllocation no_gc;
251    String::FlatContent content = literal->GetFlatContent();
252    if (content.IsOneByte()) {
253      return GetOneByteString(content.ToOneByteVector());
254    }
255    DCHECK(content.IsTwoByte());
256    return GetTwoByteString(content.ToUC16Vector());
257  }
258  
259  
NewConsString(const AstString * left,const AstString * right)260  const AstConsString* AstValueFactory::NewConsString(
261      const AstString* left, const AstString* right) {
262    // This Vector will be valid as long as the Collector is alive (meaning that
263    // the AstRawString will not be moved).
264    AstConsString* new_string = new (zone_) AstConsString(left, right);
265    strings_.Add(new_string);
266    if (isolate_) {
267      new_string->Internalize(isolate_);
268    }
269    return new_string;
270  }
271  
272  
Internalize(Isolate * isolate)273  void AstValueFactory::Internalize(Isolate* isolate) {
274    if (isolate_) {
275      // Everything is already internalized.
276      return;
277    }
278    // Strings need to be internalized before values, because values refer to
279    // strings.
280    for (int i = 0; i < strings_.length(); ++i) {
281      strings_[i]->Internalize(isolate);
282    }
283    for (int i = 0; i < values_.length(); ++i) {
284      values_[i]->Internalize(isolate);
285    }
286    isolate_ = isolate;
287  }
288  
289  
NewString(const AstRawString * string)290  const AstValue* AstValueFactory::NewString(const AstRawString* string) {
291    AstValue* value = new (zone_) AstValue(string);
292    DCHECK(string != NULL);
293    if (isolate_) {
294      value->Internalize(isolate_);
295    }
296    values_.Add(value);
297    return value;
298  }
299  
300  
NewSymbol(const char * name)301  const AstValue* AstValueFactory::NewSymbol(const char* name) {
302    AstValue* value = new (zone_) AstValue(name);
303    if (isolate_) {
304      value->Internalize(isolate_);
305    }
306    values_.Add(value);
307    return value;
308  }
309  
310  
NewNumber(double number)311  const AstValue* AstValueFactory::NewNumber(double number) {
312    AstValue* value = new (zone_) AstValue(number);
313    if (isolate_) {
314      value->Internalize(isolate_);
315    }
316    values_.Add(value);
317    return value;
318  }
319  
320  
NewSmi(int number)321  const AstValue* AstValueFactory::NewSmi(int number) {
322    AstValue* value =
323        new (zone_) AstValue(AstValue::SMI, number);
324    if (isolate_) {
325      value->Internalize(isolate_);
326    }
327    values_.Add(value);
328    return value;
329  }
330  
331  
NewBoolean(bool b)332  const AstValue* AstValueFactory::NewBoolean(bool b) {
333    AstValue* value = new (zone_) AstValue(b);
334    if (isolate_) {
335      value->Internalize(isolate_);
336    }
337    values_.Add(value);
338    return value;
339  }
340  
341  
NewStringList(ZoneList<const AstRawString * > * strings)342  const AstValue* AstValueFactory::NewStringList(
343      ZoneList<const AstRawString*>* strings) {
344    AstValue* value = new (zone_) AstValue(strings);
345    if (isolate_) {
346      value->Internalize(isolate_);
347    }
348    values_.Add(value);
349    return value;
350  }
351  
352  
NewNull()353  const AstValue* AstValueFactory::NewNull() {
354    AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
355    if (isolate_) {
356      value->Internalize(isolate_);
357    }
358    values_.Add(value);
359    return value;
360  }
361  
362  
NewUndefined()363  const AstValue* AstValueFactory::NewUndefined() {
364    AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
365    if (isolate_) {
366      value->Internalize(isolate_);
367    }
368    values_.Add(value);
369    return value;
370  }
371  
372  
NewTheHole()373  const AstValue* AstValueFactory::NewTheHole() {
374    AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
375    if (isolate_) {
376      value->Internalize(isolate_);
377    }
378    values_.Add(value);
379    return value;
380  }
381  
382  
GetString(uint32_t hash,bool is_one_byte,Vector<const byte> literal_bytes)383  const AstRawString* AstValueFactory::GetString(
384      uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) {
385    // literal_bytes here points to whatever the user passed, and this is OK
386    // because we use vector_compare (which checks the contents) to compare
387    // against the AstRawStrings which are in the string_table_. We should not
388    // return this AstRawString.
389    AstRawString key(is_one_byte, literal_bytes, hash);
390    HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
391    if (entry->value == NULL) {
392      // Copy literal contents for later comparison.
393      int length = literal_bytes.length();
394      byte* new_literal_bytes = zone_->NewArray<byte>(length);
395      memcpy(new_literal_bytes, literal_bytes.start(), length);
396      AstRawString* new_string = new (zone_) AstRawString(
397          is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
398      entry->key = new_string;
399      strings_.Add(new_string);
400      if (isolate_) {
401        new_string->Internalize(isolate_);
402      }
403      entry->value = reinterpret_cast<void*>(1);
404    }
405    return reinterpret_cast<AstRawString*>(entry->key);
406  }
407  
408  
409  } }  // namespace v8::internal
410