V8 Project
ast-value-factory.cc
Go to the documentation of this file.
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.
40  public:
42  literal_bytes_(lb), pos_(0) {}
43 
44  bool HasMore() { return pos_ < literal_bytes_.length(); }
45  uint16_t GetNext() { return literal_bytes_[pos_++]; }
46 
47  private:
49  int pos_;
50 };
51 
52 }
53 
55  public:
57  : string_(string) {}
58 
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(
64  }
65 
66  virtual uint32_t Hash() OVERRIDE {
67  return string_->hash() >> Name::kHashShift;
68  }
69 
71  return String::cast(key)->Hash();
72  }
73 
75  if (string_->is_one_byte_)
76  return isolate->factory()->NewOneByteInternalizedString(
78  return isolate->factory()->NewTwoByteInternalizedString(
80  }
81 
82  private:
84 };
85 
86 
88  if (!string_.is_null()) return;
89  if (literal_bytes_.length() == 0) {
90  string_ = isolate->factory()->empty_string();
91  } else {
93  string_ = StringTable::LookupKey(isolate, &key);
94  }
95 }
96 
97 
99  if (!string_.is_null())
100  return string_->AsArrayIndex(index);
101  if (!is_one_byte_ || literal_bytes_.length() == 0 ||
103  return false;
104  OneByteStringStream stream(literal_bytes_);
105  return StringToArrayIndex(&stream, index);
106 }
107 
108 
109 bool AstRawString::IsOneByteEqualTo(const char* data) const {
110  int length = static_cast<int>(strlen(data));
112  const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
113  return !strncmp(token, data, length);
114  }
115  return false;
116 }
117 
118 
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 
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 
141  if (type_ == STRING) {
142  uint32_t index;
143  return !string_->AsArrayIndex(&index);
144  }
145  return false;
146 }
147 
148 
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 
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:
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
virtual void Internalize(Isolate *isolate) OVERRIDE
virtual uint32_t HashForObject(Object *key) OVERRIDE
virtual bool IsMatch(Object *other) OVERRIDE
AstRawStringInternalizationKey(const AstRawString *string)
virtual Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
virtual void Internalize(Isolate *isolate) OVERRIDE
Vector< const byte > literal_bytes_
bool IsOneByteEqualTo(const char *data) const
static bool Compare(void *a, void *b)
bool AsArrayIndex(uint32_t *index) const
virtual int length() const OVERRIDE
Handle< String > string_
Handle< String > string() const
void Internalize(Isolate *isolate)
const AstValue * NewStringList(ZoneList< const AstRawString * > *strings)
const AstRawString * GetTwoByteString(Vector< const uint16_t > literal)
const AstRawString * GetOneByteString(Vector< const uint8_t > literal)
const AstValue * NewNumber(double number)
const AstValue * NewSmi(int number)
const AstConsString * NewConsString(const AstString *left, const AstString *right)
const AstRawString * GetString(Handle< String > literal)
const AstValue * NewString(const AstRawString *string)
const AstValue * NewBoolean(bool b)
const AstValue * NewSymbol(const char *name)
const AstRawString * string_
void Internalize(Isolate *isolate)
ZoneList< const AstRawString * > * strings_
bool is_null() const
Definition: handles.h:124
Handle< Context > native_context()
Definition: isolate.cc:1339
Factory * factory()
Definition: isolate.h:982
static const int kHashShift
Definition: objects.h:8499
static MUST_USE_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it)
Definition: objects.cc:109
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
static Handle< String > LookupKey(Isolate *isolate, HashTableKey *key)
Definition: objects.cc:14713
Vector< const uint8_t > ToOneByteVector()
Definition: objects.h:8639
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:8645
static const int kMaxArrayIndexSize
Definition: objects.h:8807
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:114
T * start() const
Definition: vector.h:47
int length() const
Definition: vector.h:41
T * NewArray(int length)
Definition: zone.h:46
#define OVERRIDE
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
unsigned short uint16_t
Definition: unicode.cc:23
bool DoubleToBoolean(double d)
Definition: utils.cc:397
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
bool StringToArrayIndex(Stream *stream, uint32_t *index)
Definition: utils.h:1431
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20