Parser: Delay internalizing strings and values.
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Jun 2014 13:31:56 +0000 (13:31 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Jun 2014 13:31:56 +0000 (13:31 +0000)
This is needed so that we can run Parser on a non-main thread (independent
of the Isolate and the V8 heap).

BUG=
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/314603004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21841 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

32 files changed:
include/v8.h
src/ast-value-factory.cc [new file with mode: 0644]
src/ast-value-factory.h [new file with mode: 0644]
src/ast.cc
src/ast.h
src/compiler.cc
src/compiler.h
src/func-name-inferrer.cc
src/func-name-inferrer.h
src/heap.h
src/interface.cc
src/interface.h
src/objects.cc
src/parser.cc
src/parser.h
src/preparser.h
src/prettyprinter.cc
src/prettyprinter.h
src/rewriter.cc
src/scanner.cc
src/scanner.h
src/scopeinfo.cc
src/scopes.cc
src/scopes.h
src/utils.cc
src/utils.h
src/variables.cc
src/variables.h
test/cctest/test-ast.cc
test/cctest/test-parsing.cc
tools/gyp/v8.gyp
tools/parser-shell.cc

index 1db14733a6e2e8699879ec631e8b0ad6507c40b4..2739e070b634cac24804eb2e8813a7d451b13fb0 100644 (file)
@@ -5543,7 +5543,7 @@ class Internals {
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 163;
+  static const int kEmptyStringRootIndex = 160;
 
   // The external allocation limit should be below 256 MB on all architectures
   // to avoid that resource-constrained embedders run low on memory.
diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc
new file mode 100644 (file)
index 0000000..a430dcd
--- /dev/null
@@ -0,0 +1,368 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/ast-value-factory.h"
+
+#include "src/api.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+template <typename Char>
+int vector_hash(Vector<const Char> string) {
+  int hash = 0;
+  for (int i = 0; i < string.length(); i++) {
+    int c = static_cast<int>(string[i]);
+    hash += c;
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+  }
+  return hash;
+}
+
+
+// For using StringToArrayIndex.
+class OneByteStringStream {
+ public:
+  explicit OneByteStringStream(Vector<const byte> lb) :
+      literal_bytes_(lb), pos_(0) {}
+
+  bool HasMore() { return pos_ < literal_bytes_.length(); }
+  uint16_t GetNext() { return literal_bytes_[pos_++]; }
+
+ private:
+  Vector<const byte> literal_bytes_;
+  int pos_;
+};
+
+}
+
+
+bool AstString::AsArrayIndex(uint32_t* index) const {
+  if (!string_.is_null())
+    return string_->AsArrayIndex(index);
+  if (!is_one_byte_ || literal_bytes_.length() == 0 ||
+      literal_bytes_.length() > String::kMaxArrayIndexSize)
+    return false;
+  OneByteStringStream stream(literal_bytes_);
+  return StringToArrayIndex(&stream, index);
+}
+
+
+bool AstString::IsOneByteEqualTo(const char* data) const {
+  int length = strlen(data);
+  if (is_one_byte_ && literal_bytes_.length() == length) {
+    const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
+    return !strncmp(token, data, length);
+  }
+  return false;
+}
+
+
+void AstString::Internalize(Isolate* isolate) {
+  if (!string_.is_null()) return;
+  if (literal_bytes_.length() == 0) {
+    string_ = isolate->factory()->empty_string();
+  } else if (is_one_byte_) {
+    string_ = isolate->factory()->InternalizeOneByteString(literal_bytes_);
+  } else {
+    string_ = isolate->factory()->InternalizeTwoByteString(
+        Vector<const uint16_t>::cast(literal_bytes_));
+  }
+}
+
+
+bool AstString::Compare(void* a, void* b) {
+  AstString* string1 = reinterpret_cast<AstString*>(a);
+  AstString* string2 = reinterpret_cast<AstString*>(b);
+  if (string1->is_one_byte_ != string2->is_one_byte_) return false;
+  if (string1->hash_ != string2->hash_) return false;
+  int length = string1->literal_bytes_.length();
+  if (string2->literal_bytes_.length() != length) return false;
+  return memcmp(string1->literal_bytes_.start(),
+                string2->literal_bytes_.start(), length) == 0;
+}
+
+
+bool AstValue::IsPropertyName() const {
+  if (type_ == STRING) {
+    uint32_t index;
+    return !string_->AsArrayIndex(&index);
+  }
+  return false;
+}
+
+
+bool AstValue::BooleanValue() const {
+  switch (type_) {
+    case STRING:
+      ASSERT(string_ != NULL);
+      return !string_->IsEmpty();
+    case SYMBOL:
+      UNREACHABLE();
+      break;
+    case NUMBER:
+      return DoubleToBoolean(number_);
+    case SMI:
+      return smi_ != 0;
+    case STRING_ARRAY:
+      UNREACHABLE();
+      break;
+    case BOOLEAN:
+      return bool_;
+    case NULL_TYPE:
+      return false;
+    case THE_HOLE:
+      UNREACHABLE();
+      break;
+    case UNDEFINED:
+      return false;
+  }
+  UNREACHABLE();
+  return false;
+}
+
+
+void AstValue::Internalize(Isolate* isolate) {
+  switch (type_) {
+    case STRING:
+      ASSERT(string_ != NULL);
+      // Strings are already internalized.
+      ASSERT(!string_->string().is_null());
+      break;
+    case SYMBOL:
+      value_ = Object::GetProperty(
+                   isolate, handle(isolate->native_context()->builtins()),
+                   symbol_name_).ToHandleChecked();
+      break;
+    case NUMBER:
+      value_ = isolate->factory()->NewNumber(number_, TENURED);
+      break;
+    case SMI:
+      value_ = handle(Smi::FromInt(smi_), isolate);
+      break;
+    case BOOLEAN:
+      if (bool_) {
+        value_ = isolate->factory()->true_value();
+      } else {
+        value_ = isolate->factory()->false_value();
+      }
+      break;
+    case STRING_ARRAY: {
+      ASSERT(strings_ != NULL);
+      Factory* factory = isolate->factory();
+      int len = strings_->length();
+      Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
+      for (int i = 0; i < len; i++) {
+        const AstString* string = (*strings_)[i];
+        Handle<Object> element = string->string();
+        // Strings are already internalized.
+        ASSERT(!element.is_null());
+        elements->set(i, *element);
+      }
+      value_ =
+          factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
+      break;
+    }
+    case NULL_TYPE:
+      value_ = isolate->factory()->null_value();
+      break;
+    case THE_HOLE:
+      value_ = isolate->factory()->the_hole_value();
+      break;
+    case UNDEFINED:
+      value_ = isolate->factory()->undefined_value();
+      break;
+  }
+}
+
+
+const AstString* AstValueFactory::GetOneByteString(
+    Vector<const uint8_t> literal) {
+  return GetString(vector_hash(literal), true, literal);
+}
+
+
+const AstString* AstValueFactory::GetTwoByteString(
+    Vector<const uint16_t> literal) {
+  return GetString(vector_hash(literal), false,
+                   Vector<const byte>::cast(literal));
+}
+
+
+const AstString* AstValueFactory::GetString(Handle<String> literal) {
+  DisallowHeapAllocation no_gc;
+  String::FlatContent content = literal->GetFlatContent();
+  if (content.IsAscii()) {
+    return GetOneByteString(content.ToOneByteVector());
+  }
+  ASSERT(content.IsTwoByte());
+  return GetTwoByteString(content.ToUC16Vector());
+}
+
+
+void AstValueFactory::Internalize(Isolate* isolate) {
+  if (isolate_) {
+    // Everything is already internalized.
+    return;
+  }
+  // Strings need to be internalized before values, because values refer to
+  // strings.
+  for (HashMap::Entry* p = string_table_.Start(); p != NULL;
+       p = string_table_.Next(p)) {
+    AstString* string = reinterpret_cast<AstString*>(p->key);
+    string->Internalize(isolate);
+  }
+  for (int i = 0; i < values_.length(); ++i) {
+    values_[i]->Internalize(isolate);
+  }
+  isolate_ = isolate;
+}
+
+
+const AstValue* AstValueFactory::NewString(const AstString* string) {
+  AstValue* value = new (zone_) AstValue(string);
+  ASSERT(string != NULL);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewSymbol(const char* name) {
+  AstValue* value = new (zone_) AstValue(name);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewNumber(double number) {
+  AstValue* value = new (zone_) AstValue(number);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewSmi(int number) {
+  AstValue* value =
+      new (zone_) AstValue(AstValue::SMI, number);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewBoolean(bool b) {
+  AstValue* value = new (zone_) AstValue(b);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewStringList(
+    ZoneList<const AstString*>* strings) {
+  AstValue* value = new (zone_) AstValue(strings);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewNull() {
+  AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewUndefined() {
+  AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewTheHole() {
+  AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstString* AstValueFactory::GetString(int hash, bool is_one_byte,
+                                            Vector<const byte> literal_bytes) {
+  // literal_bytes here points to whatever the user passed, and this is OK
+  // because we use vector_compare (which checks the contents) to compare
+  // against the AstStrings which are in the string_table_. We should not return
+  // this AstString.
+  AstString key(is_one_byte, literal_bytes, hash);
+  HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
+  if (entry->value == NULL) {
+    // Copy literal contents for later comparison.
+    key.literal_bytes_ =
+        Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
+    // This Vector will be valid as long as the Collector is alive (meaning that
+    // the AstString will not be moved).
+    Vector<AstString> new_string = string_table_keys_.AddBlock(1, key);
+    entry->key = &new_string[0];
+    if (isolate_) {
+      new_string[0].Internalize(isolate_);
+    }
+    entry->value = reinterpret_cast<void*>(1);
+  }
+  return reinterpret_cast<AstString*>(entry->key);
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h
new file mode 100644 (file)
index 0000000..8b3a7c3
--- /dev/null
@@ -0,0 +1,294 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_AST_VALUE_FACTORY_H_
+#define V8_AST_VALUE_FACTORY_H_
+
+#include "src/api.h"
+#include "src/hashmap.h"
+#include "src/utils.h"
+
+// AstString, AstValue and AstValueFactory are for storing strings and values
+// independent of the V8 heap and internalizing them later. During parsing,
+// AstStrings and AstValues are created and stored outside the heap, in
+// AstValueFactory. After parsing, the strings and values are internalized
+// (moved into the V8 heap).
+namespace v8 {
+namespace internal {
+
+class AstString {
+ public:
+  AstString(bool i, Vector<const byte> lb, int h)
+      : is_one_byte_(i),
+        literal_bytes_(lb),
+        hash_(h) {}
+
+  AstString()
+      : is_one_byte_(true),
+        hash_(0) {}
+
+  bool AsArrayIndex(uint32_t* index) const;
+
+  // The string is not null-terminated, use length() to find out the length.
+  const unsigned char* raw_data() const { return literal_bytes_.start(); }
+  int length() const {
+    if (is_one_byte_)
+      return literal_bytes_.length();
+    return literal_bytes_.length() / 2;
+  }
+  bool is_one_byte() const { return is_one_byte_; }
+  bool IsEmpty() const { return literal_bytes_.length() == 0; }
+  bool IsOneByteEqualTo(const char* data) const;
+  uint16_t FirstCharacter() const {
+    if (is_one_byte_)
+      return literal_bytes_[0];
+    const uint16_t* c =
+        reinterpret_cast<const uint16_t*>(literal_bytes_.start());
+    return *c;
+  }
+
+  // Puts the string into the V8 heap.
+  void Internalize(Isolate* isolate);
+
+  // This function can be called after internalizing.
+  V8_INLINE Handle<String> string() const {
+    ASSERT(!string_.is_null());
+    return string_;
+  }
+
+  // For storing AstStrings in a hash map.
+  int hash() const { return hash_; }
+  static bool Compare(void* a, void* b);
+
+ private:
+  friend class AstValueFactory;
+
+  bool is_one_byte_;
+  // Weak. Points to memory owned by AstValueFactory.
+  Vector<const byte> literal_bytes_;
+  int hash_;
+
+  // This is null until the string is internalized.
+  Handle<String> string_;
+};
+
+
+// AstValue is either a string, a number, a string array, a boolean, or a
+// special value (null, undefined, the hole).
+class AstValue : public ZoneObject {
+ public:
+  bool IsString() const {
+    return type_ == STRING;
+  }
+
+  bool IsNumber() const {
+    return type_ == NUMBER || type_ == SMI;
+  }
+
+  const AstString* AsString() const {
+    if (type_ == STRING)
+      return string_;
+    UNREACHABLE();
+    return 0;
+  }
+
+  double AsNumber() const {
+    if (type_ == NUMBER)
+      return number_;
+    if (type_ == SMI)
+      return smi_;
+    UNREACHABLE();
+    return 0;
+  }
+
+  bool EqualsString(const AstString* string) const {
+    return type_ == STRING && string_ == string;
+  }
+
+  bool IsPropertyName() const;
+
+  bool BooleanValue() const;
+
+  void Internalize(Isolate* isolate);
+
+  // Can be called after Internalize has been called.
+  V8_INLINE Handle<Object> value() const {
+    if (type_ == STRING) {
+      return string_->string();
+    }
+    ASSERT(!value_.is_null());
+    return value_;
+  }
+
+ private:
+  friend class AstValueFactory;
+
+  enum Type {
+    STRING,
+    SYMBOL,
+    NUMBER,
+    SMI,
+    BOOLEAN,
+    STRING_ARRAY,
+    NULL_TYPE,
+    UNDEFINED,
+    THE_HOLE
+  };
+
+  explicit AstValue(const AstString* s) : type_(STRING) { string_ = s; }
+
+  explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; }
+
+  explicit AstValue(double n) : type_(NUMBER) { number_ = n; }
+
+  AstValue(Type t, int i) : type_(t) {
+    ASSERT(type_ == SMI);
+    smi_ = i;
+  }
+
+  explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; }
+
+  explicit AstValue(ZoneList<const AstString*>* s) : type_(STRING_ARRAY) {
+    strings_ = s;
+  }
+
+  explicit AstValue(Type t) : type_(t) {
+    ASSERT(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
+  }
+
+  Type type_;
+
+  // Uninternalized value.
+  union {
+    const AstString* string_;
+    double number_;
+    int smi_;
+    bool bool_;
+    ZoneList<const AstString*>* strings_;
+    const char* symbol_name_;
+  };
+
+  // Internalized value (empty before internalized).
+  Handle<Object> value_;
+};
+
+
+// For generating string constants.
+#define STRING_CONSTANTS(F) \
+  F(anonymous_function, "(anonymous function)") \
+  F(arguments, "arguments") \
+  F(done, "done") \
+  F(dot_for, ".for") \
+  F(dot_generator, ".generator") \
+  F(dot_generator_object, ".generator_object") \
+  F(dot_iterable, ".iterable") \
+  F(dot_iterator, ".iterator") \
+  F(dot_module, ".module") \
+  F(dot_result, ".result") \
+  F(empty, "") \
+  F(eval, "eval") \
+  F(initialize_const_global, "initializeConstGlobal") \
+  F(initialize_var_global, "initializeVarGlobal") \
+  F(make_reference_error, "MakeReferenceError") \
+  F(make_syntax_error, "MakeSyntaxError") \
+  F(make_type_error, "MakeTypeError") \
+  F(module, "module") \
+  F(native, "native") \
+  F(next, "next") \
+  F(proto, "__proto__") \
+  F(prototype, "prototype") \
+  F(this, "this") \
+  F(use_strict, "use strict") \
+  F(value, "value")
+
+class AstValueFactory {
+ public:
+  explicit AstValueFactory(Zone* zone)
+      : literal_chars_(0),
+        string_table_keys_(0),
+        string_table_(AstString::Compare),
+        zone_(zone),
+        isolate_(NULL) {
+#define F(name, str) {      \
+      const char* data = str;          \
+      name##_string_ = GetOneByteString(                              \
+          Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \
+                                strlen(data)));                         \
+    }
+    STRING_CONSTANTS(F)
+#undef F
+  }
+
+  const AstString* GetOneByteString(Vector<const uint8_t> literal);
+  const AstString* GetTwoByteString(Vector<const uint16_t> literal);
+  const AstString* GetString(Handle<String> literal);
+
+  void Internalize(Isolate* isolate);
+
+#define F(name, str) \
+  const AstString* name##_string() const { return name##_string_; }
+  STRING_CONSTANTS(F)
+#undef F
+
+  const AstValue* NewString(const AstString* string);
+  // A JavaScript symbol (ECMA-262 edition 6).
+  const AstValue* NewSymbol(const char* name);
+  const AstValue* NewNumber(double number);
+  const AstValue* NewSmi(int number);
+  const AstValue* NewBoolean(bool b);
+  const AstValue* NewStringList(ZoneList<const AstString*>* strings);
+  const AstValue* NewNull();
+  const AstValue* NewUndefined();
+  const AstValue* NewTheHole();
+
+ private:
+  const AstString* GetString(int hash, bool is_one_byte,
+                             Vector<const byte> literal_bytes);
+
+  // All strings are copied here, one after another (no NULLs inbetween).
+  Collector<byte> literal_chars_;
+  // List of all AstStrings we have created; keys of string_table_ are pointers
+  // into AstStrings in string_table_keys_.
+  Collector<AstString> string_table_keys_;
+  HashMap string_table_;
+  // For keeping track of all AstValues we've created (so that they can be
+  // internalized later).
+  List<AstValue*> values_;
+  Zone* zone_;
+  Isolate* isolate_;
+
+#define F(name, str) \
+  const AstString* name##_string_;
+  STRING_CONSTANTS(F)
+#undef F
+};
+
+} }  // namespace v8::internal
+
+#undef STRING_CONSTANTS
+
+#endif  // V8_AST_VALUE_FACTORY_H_
index 8b1d94176fb7c3b20068a0e8d530bf00c2922a48..59415c9e86c6702482b79757ee01a30a693acf05 100644 (file)
@@ -55,14 +55,13 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
   // The global identifier "undefined" is immutable. Everything
   // else could be reassigned.
   return var != NULL && var->location() == Variable::UNALLOCATED &&
-         String::Equals(var_proxy->name(),
-                        isolate->factory()->undefined_string());
+         var_proxy->raw_name()->IsOneByteEqualTo("undefined");
 }
 
 
 VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
     : Expression(zone, position),
-      name_(var->name()),
+      name_(var->raw_name()),
       var_(NULL),  // Will be set by the call to BindTo.
       is_this_(var->is_this()),
       is_trivial_(false),
@@ -73,7 +72,7 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
 
 
 VariableProxy::VariableProxy(Zone* zone,
-                             Handle<String> name,
+                             const AstString* name,
                              bool is_this,
                              Interface* interface,
                              int position)
@@ -84,8 +83,6 @@ VariableProxy::VariableProxy(Zone* zone,
       is_trivial_(false),
       is_lvalue_(false),
       interface_(interface) {
-  // Names must be canonicalized for fast equality checks.
-  ASSERT(name->IsInternalizedString());
 }
 
 
@@ -93,7 +90,7 @@ void VariableProxy::BindTo(Variable* var) {
   ASSERT(var_ == NULL);  // must be bound only once
   ASSERT(var != NULL);  // must bind
   ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
-  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
+  ASSERT((is_this() && var->is_this()) || name_ == var->raw_name());
   // Ideally CONST-ness should match. However, this is very hard to achieve
   // because we don't know the exact semantics of conflicting (const and
   // non-const) multiple variable declarations, const vars introduced via
@@ -180,15 +177,13 @@ void FunctionLiteral::InitializeSharedInfo(
 }
 
 
-ObjectLiteralProperty::ObjectLiteralProperty(
-    Zone* zone, Literal* key, Expression* value) {
+ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
+                                             AstValueFactory* ast_value_factory,
+                                             Literal* key, Expression* value) {
   emit_store_ = true;
   key_ = key;
   value_ = value;
-  Handle<Object> k = key->value();
-  if (k->IsInternalizedString() &&
-      String::Equals(Handle<String>::cast(k),
-                     zone->isolate()->factory()->proto_string())) {
+  if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
     kind_ = PROTOTYPE;
   } else if (value_->AsMaterializedLiteral() != NULL) {
     kind_ = MATERIALIZED_LITERAL;
@@ -1122,9 +1117,8 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
     // optimize them.
     add_flag(kDontInline);
   } else if (node->function()->intrinsic_type == Runtime::INLINE &&
-      (node->name()->IsOneByteEqualTo(
-          STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
-       node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
+             (node->raw_name()->IsOneByteEqualTo("_ArgumentsLength") ||
+              node->raw_name()->IsOneByteEqualTo("_Arguments"))) {
     // Don't inline the %_ArgumentsLength or %_Arguments because their
     // implementation will not work.  There is no stack frame to get them
     // from.
@@ -1139,17 +1133,17 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
 
 
 Handle<String> Literal::ToString() {
-  if (value_->IsString()) return Handle<String>::cast(value_);
+  if (value_->IsString()) return value_->AsString()->string();
   ASSERT(value_->IsNumber());
   char arr[100];
   Vector<char> buffer(arr, ARRAY_SIZE(arr));
   const char* str;
-  if (value_->IsSmi()) {
+  if (value()->IsSmi()) {
     // Optimization only, the heap number case would subsume this.
-    OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value());
+    OS::SNPrintF(buffer, "%d", Smi::cast(*value())->value());
     str = arr;
   } else {
-    str = DoubleToCString(value_->Number(), buffer);
+    str = DoubleToCString(value()->Number(), buffer);
   }
   return isolate_->factory()->NewStringFromAsciiChecked(str);
 }
index f79c2d2b2b0ce1391b64cd4806d4d42e321ba112..196b4e77eca5aefb0af763744c1ef3b6535faea3 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -8,6 +8,7 @@
 #include "src/v8.h"
 
 #include "src/assembler.h"
+#include "src/ast-value-factory.h"
 #include "src/factory.h"
 #include "src/feedback-slots.h"
 #include "src/isolate.h"
@@ -367,11 +368,14 @@ class Expression : public AstNode {
  protected:
   Expression(Zone* zone, int pos)
       : AstNode(pos),
+        zone_(zone),
         bounds_(Bounds::Unbounded(zone)),
         id_(GetNextId(zone)),
         test_id_(GetNextId(zone)) {}
   void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
 
+  Zone* zone_;
+
  private:
   Bounds bounds_;
   byte to_boolean_types_;
@@ -390,7 +394,7 @@ class BreakableStatement : public Statement {
 
   // The labels associated with this statement. May be NULL;
   // if it is != NULL, guaranteed to contain at least one entry.
-  ZoneStringList* labels() const { return labels_; }
+  ZoneList<const AstString*>* labels() const { return labels_; }
 
   // Type testing & conversion.
   virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE {
@@ -410,7 +414,7 @@ class BreakableStatement : public Statement {
 
  protected:
   BreakableStatement(
-      Zone* zone, ZoneStringList* labels,
+      Zone* zone, ZoneList<const AstString*>* labels,
       BreakableType breakable_type, int position)
       : Statement(zone, position),
         labels_(labels),
@@ -422,7 +426,7 @@ class BreakableStatement : public Statement {
 
 
  private:
-  ZoneStringList* labels_;
+  ZoneList<const AstString*>* labels_;
   BreakableType breakable_type_;
   Label break_target_;
   const BailoutId entry_id_;
@@ -453,7 +457,7 @@ class Block V8_FINAL : public BreakableStatement {
 
  protected:
   Block(Zone* zone,
-        ZoneStringList* labels,
+        ZoneList<const AstString*>* labels,
         int capacity,
         bool is_initializer_block,
         int pos)
@@ -662,18 +666,15 @@ class ModulePath V8_FINAL : public Module {
   DECLARE_NODE_TYPE(ModulePath)
 
   Module* module() const { return module_; }
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
 
  protected:
-  ModulePath(Zone* zone, Module* module, Handle<String> name, int pos)
-      : Module(zone, pos),
-        module_(module),
-        name_(name) {
-  }
+  ModulePath(Zone* zone, Module* module, const AstString* name, int pos)
+      : Module(zone, pos), module_(module), name_(name) {}
 
  private:
   Module* module_;
-  Handle<String> name_;
+  const AstString* name_;
 };
 
 
@@ -730,7 +731,7 @@ class IterationStatement : public BreakableStatement {
   Label* continue_target()  { return &continue_target_; }
 
  protected:
-  IterationStatement(Zone* zone, ZoneStringList* labels, int pos)
+  IterationStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         body_(NULL),
         osr_entry_id_(GetNextId(zone)) {
@@ -764,7 +765,7 @@ class DoWhileStatement V8_FINAL : public IterationStatement {
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+  DoWhileStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         cond_(NULL),
         continue_id_(GetNextId(zone)),
@@ -801,7 +802,7 @@ class WhileStatement V8_FINAL : public IterationStatement {
   BailoutId BodyId() const { return body_id_; }
 
  protected:
-  WhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+  WhileStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         cond_(NULL),
         may_have_function_literal_(true),
@@ -852,7 +853,7 @@ class ForStatement V8_FINAL : public IterationStatement {
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
 
  protected:
-  ForStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         init_(NULL),
         cond_(NULL),
@@ -894,11 +895,8 @@ class ForEachStatement : public IterationStatement {
   Expression* subject() const { return subject_; }
 
  protected:
-  ForEachStatement(Zone* zone, ZoneStringList* labels, int pos)
-      : IterationStatement(zone, labels, pos),
-        each_(NULL),
-        subject_(NULL) {
-  }
+  ForEachStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
 
  private:
   Expression* each_;
@@ -934,7 +932,7 @@ class ForInStatement V8_FINAL : public ForEachStatement,
   virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
 
  protected:
-  ForInStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForInStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : ForEachStatement(zone, labels, pos),
         for_in_type_(SLOW_FOR_IN),
         for_in_feedback_slot_(kInvalidFeedbackSlot),
@@ -1004,7 +1002,7 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  ForOfStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForOfStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : ForEachStatement(zone, labels, pos),
         assign_iterator_(NULL),
         next_result_(NULL),
@@ -1165,7 +1163,7 @@ class SwitchStatement V8_FINAL : public BreakableStatement {
   ZoneList<CaseClause*>* cases() const { return cases_; }
 
  protected:
-  SwitchStatement(Zone* zone, ZoneStringList* labels, int pos)
+  SwitchStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         tag_(NULL),
         cases_(NULL) { }
@@ -1345,26 +1343,28 @@ class Literal V8_FINAL : public Expression {
   DECLARE_NODE_TYPE(Literal)
 
   virtual bool IsPropertyName() const V8_OVERRIDE {
-    if (value_->IsInternalizedString()) {
-      uint32_t ignored;
-      return !String::cast(*value_)->AsArrayIndex(&ignored);
-    }
-    return false;
+    return value_->IsPropertyName();
   }
 
   Handle<String> AsPropertyName() {
     ASSERT(IsPropertyName());
-    return Handle<String>::cast(value_);
+    return Handle<String>::cast(value());
+  }
+
+  const AstString* AsRawPropertyName() {
+    ASSERT(IsPropertyName());
+    return value_->AsString();
   }
 
   virtual bool ToBooleanIsTrue() const V8_OVERRIDE {
-    return value_->BooleanValue();
+    return value()->BooleanValue();
   }
   virtual bool ToBooleanIsFalse() const V8_OVERRIDE {
-    return !value_->BooleanValue();
+    return !value()->BooleanValue();
   }
 
-  Handle<Object> value() const { return value_; }
+  Handle<Object> value() const { return value_->value(); }
+  const AstValue* raw_value() const { return value_; }
 
   // Support for using Literal as a HashMap key. NOTE: Currently, this works
   // only for string and number literals!
@@ -1379,7 +1379,7 @@ class Literal V8_FINAL : public Expression {
   TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
 
  protected:
-  Literal(Zone* zone, Handle<Object> value, int position)
+  Literal(Zone* zone, const AstValue* value, int position)
       : Expression(zone, position),
         value_(value),
         isolate_(zone->isolate()) { }
@@ -1387,7 +1387,7 @@ class Literal V8_FINAL : public Expression {
  private:
   Handle<String> ToString();
 
-  Handle<Object> value_;
+  const AstValue* value_;
   // TODO(dcarney): remove.  this is only needed for Match and Hash.
   Isolate* isolate_;
 };
@@ -1458,7 +1458,8 @@ class ObjectLiteralProperty V8_FINAL : public ZoneObject {
     PROTOTYPE              // Property is __proto__.
   };
 
-  ObjectLiteralProperty(Zone* zone, Literal* key, Expression* value);
+  ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory,
+                        Literal* key, Expression* value);
 
   Literal* key() { return key_; }
   Expression* value() { return value_; }
@@ -1557,13 +1558,13 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
  public:
   DECLARE_NODE_TYPE(RegExpLiteral)
 
-  Handle<String> pattern() const { return pattern_; }
-  Handle<String> flags() const { return flags_; }
+  Handle<String> pattern() const { return pattern_->string(); }
+  Handle<String> flags() const { return flags_->string(); }
 
  protected:
   RegExpLiteral(Zone* zone,
-                Handle<String> pattern,
-                Handle<String> flags,
+                const AstString* pattern,
+                const AstString* flags,
                 int literal_index,
                 int pos)
       : MaterializedLiteral(zone, literal_index, pos),
@@ -1573,8 +1574,8 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
   }
 
  private:
-  Handle<String> pattern_;
-  Handle<String> flags_;
+  const AstString* pattern_;
+  const AstString* flags_;
 };
 
 
@@ -1625,15 +1626,12 @@ class VariableProxy V8_FINAL : public Expression {
     return var_ == NULL ? true : var_->IsValidReference();
   }
 
-  bool IsVariable(Handle<String> n) const {
-    return !is_this() && name().is_identical_to(n);
-  }
-
   bool IsArguments() const { return var_ != NULL && var_->is_arguments(); }
 
   bool IsLValue() const { return is_lvalue_; }
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
+  const AstString* raw_name() const { return name_; }
   Variable* var() const { return var_; }
   bool is_this() const { return is_this_; }
   Interface* interface() const { return interface_; }
@@ -1649,12 +1647,12 @@ class VariableProxy V8_FINAL : public Expression {
   VariableProxy(Zone* zone, Variable* var, int position);
 
   VariableProxy(Zone* zone,
-                Handle<String> name,
+                const AstString* name,
                 bool is_this,
                 Interface* interface,
                 int position);
 
-  Handle<String> name_;
+  const AstString* name_;
   Variable* var_;  // resolved variable, or NULL
   bool is_this_;
   bool is_trivial_;
@@ -1900,7 +1898,8 @@ class CallRuntime V8_FINAL : public Expression {
  public:
   DECLARE_NODE_TYPE(CallRuntime)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return raw_name_->string(); }
+  const AstString* raw_name() const { return raw_name_; }
   const Runtime::Function* function() const { return function_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
   bool is_jsruntime() const { return function_ == NULL; }
@@ -1909,17 +1908,17 @@ class CallRuntime V8_FINAL : public Expression {
 
  protected:
   CallRuntime(Zone* zone,
-              Handle<String> name,
+              const AstString* name,
               const Runtime::Function* function,
               ZoneList<Expression*>* arguments,
               int pos)
       : Expression(zone, pos),
-        name_(name),
+        raw_name_(name),
         function_(function),
         arguments_(arguments) { }
 
  private:
-  Handle<String> name_;
+  const AstString* raw_name_;
   const Runtime::Function* function_;
   ZoneList<Expression*>* arguments_;
 };
@@ -2307,7 +2306,8 @@ class FunctionLiteral V8_FINAL : public Expression {
 
   DECLARE_NODE_TYPE(FunctionLiteral)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return raw_name_->string(); }
+  const AstString* raw_name() const { return raw_name_; }
   Scope* scope() const { return scope_; }
   ZoneList<Statement*>* body() const { return body_; }
   void set_function_token_position(int pos) { function_token_position_ = pos; }
@@ -2330,13 +2330,35 @@ class FunctionLiteral V8_FINAL : public Expression {
   void InitializeSharedInfo(Handle<Code> code);
 
   Handle<String> debug_name() const {
-    if (name_->length() > 0) return name_;
+    if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
+      return raw_name_->string();
+    }
     return inferred_name();
   }
 
-  Handle<String> inferred_name() const { return inferred_name_; }
+  Handle<String> inferred_name() const {
+    if (!inferred_name_.is_null()) {
+      ASSERT(raw_inferred_name_ == NULL);
+      return inferred_name_;
+    }
+    if (raw_inferred_name_ != NULL) {
+      return raw_inferred_name_->string();
+    }
+    UNREACHABLE();
+    return Handle<String>();
+  }
+
+  // Only one of {set_inferred_name, set_raw_inferred_name} should be called.
   void set_inferred_name(Handle<String> inferred_name) {
     inferred_name_ = inferred_name;
+    ASSERT(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty());
+    raw_inferred_name_ = NULL;
+  }
+
+  void set_raw_inferred_name(const AstString* raw_inferred_name) {
+    raw_inferred_name_ = raw_inferred_name;
+    ASSERT(inferred_name_.is_null());
+    inferred_name_ = Handle<String>();
   }
 
   // shared_info may be null if it's not cached in full code.
@@ -2383,7 +2405,8 @@ class FunctionLiteral V8_FINAL : public Expression {
 
  protected:
   FunctionLiteral(Zone* zone,
-                  Handle<String> name,
+                  const AstString* name,
+                  AstValueFactory* ast_value_factory,
                   Scope* scope,
                   ZoneList<Statement*>* body,
                   int materialized_literal_count,
@@ -2397,10 +2420,10 @@ class FunctionLiteral V8_FINAL : public Expression {
                   IsGeneratorFlag is_generator,
                   int position)
       : Expression(zone, position),
-        name_(name),
+        raw_name_(name),
         scope_(scope),
         body_(body),
-        inferred_name_(zone->isolate()->factory()->empty_string()),
+        raw_inferred_name_(ast_value_factory->empty_string()),
         dont_optimize_reason_(kNoReason),
         materialized_literal_count_(materialized_literal_count),
         expected_property_count_(expected_property_count),
@@ -2418,10 +2441,12 @@ class FunctionLiteral V8_FINAL : public Expression {
   }
 
  private:
+  const AstString* raw_name_;
   Handle<String> name_;
   Handle<SharedFunctionInfo> shared_info_;
   Scope* scope_;
   ZoneList<Statement*>* body_;
+  const AstString* raw_inferred_name_;
   Handle<String> inferred_name_;
   AstProperties ast_properties_;
   BailoutReason dont_optimize_reason_;
@@ -2447,16 +2472,16 @@ class NativeFunctionLiteral V8_FINAL : public Expression {
  public:
   DECLARE_NODE_TYPE(NativeFunctionLiteral)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
   v8::Extension* extension() const { return extension_; }
 
  protected:
-  NativeFunctionLiteral(
-      Zone* zone, Handle<String> name, v8::Extension* extension, int pos)
+  NativeFunctionLiteral(Zone* zone, const AstString* name,
+                        v8::Extension* extension, int pos)
       : Expression(zone, pos), name_(name), extension_(extension) {}
 
  private:
-  Handle<String> name_;
+  const AstString* name_;
   v8::Extension* extension_;
 };
 
@@ -2948,7 +2973,8 @@ class AstNullVisitor BASE_EMBEDDED {
 template<class Visitor>
 class AstNodeFactory V8_FINAL BASE_EMBEDDED {
  public:
-  explicit AstNodeFactory(Zone* zone) : zone_(zone) { }
+  explicit AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory)
+      : zone_(zone), ast_value_factory_(ast_value_factory) {}
 
   Visitor* visitor() { return &visitor_; }
 
@@ -3012,8 +3038,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(ModuleVariable, module)
   }
 
-  ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) {
-    ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos);
+  ModulePath* NewModulePath(Module* origin, const AstString* name, int pos) {
+    ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos);
     VISIT_AND_RETURN(ModulePath, module)
   }
 
@@ -3022,7 +3048,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(ModuleUrl, module)
   }
 
-  Block* NewBlock(ZoneStringList* labels,
+  Block* NewBlock(ZoneList<const AstString*>* labels,
                   int capacity,
                   bool is_initializer_block,
                   int pos) {
@@ -3032,7 +3058,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
   }
 
 #define STATEMENT_WITH_LABELS(NodeType) \
-  NodeType* New##NodeType(ZoneStringList* labels, int pos) { \
+  NodeType* New##NodeType(ZoneList<const AstString*>* labels, int pos) { \
     NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \
     VISIT_AND_RETURN(NodeType, stmt); \
   }
@@ -3043,7 +3069,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
 #undef STATEMENT_WITH_LABELS
 
   ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
-                                        ZoneStringList* labels,
+                                        ZoneList<const AstString*>* labels,
                                         int pos) {
     switch (visit_mode) {
       case ForEachStatement::ENUMERATE: {
@@ -3140,14 +3166,59 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(CaseClause, clause)
   }
 
-  Literal* NewLiteral(Handle<Object> handle, int pos) {
-    Literal* lit = new(zone_) Literal(zone_, handle, pos);
+  Literal* NewStringLiteral(const AstString* string, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  // A JavaScript symbol (ECMA-262 edition 6).
+  Literal* NewSymbolLiteral(const char* name, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewNumberLiteral(double number, int pos) {
-    return NewLiteral(
-        zone_->isolate()->factory()->NewNumber(number, TENURED), pos);
+    Literal* lit = new (zone_)
+        Literal(zone_, ast_value_factory_->NewNumber(number), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewSmiLiteral(int number, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewBooleanLiteral(bool b, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewStringListLiteral(ZoneList<const AstString*>* strings, int pos) {
+    Literal* lit = new (zone_)
+        Literal(zone_, ast_value_factory_->NewStringList(strings), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewNullLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewUndefinedLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewTheHoleLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos);
+    VISIT_AND_RETURN(Literal, lit)
   }
 
   ObjectLiteral* NewObjectLiteral(
@@ -3164,7 +3235,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
 
   ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
                                                     Expression* value) {
-    return new(zone_) ObjectLiteral::Property(zone_, key, value);
+    return new (zone_)
+        ObjectLiteral::Property(zone_, ast_value_factory_, key, value);
   }
 
   ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
@@ -3172,12 +3244,12 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
                                                     int pos) {
     ObjectLiteral::Property* prop =
         new(zone_) ObjectLiteral::Property(zone_, is_getter, value);
-    prop->set_key(NewLiteral(value->name(), pos));
+    prop->set_key(NewStringLiteral(value->raw_name(), pos));
     return prop;  // Not an AST node, will not be visited.
   }
 
-  RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
-                                  Handle<String> flags,
+  RegExpLiteral* NewRegExpLiteral(const AstString* pattern,
+                                  const AstString* flags,
                                   int literal_index,
                                   int pos) {
     RegExpLiteral* lit =
@@ -3199,7 +3271,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(VariableProxy, proxy)
   }
 
-  VariableProxy* NewVariableProxy(Handle<String> name,
+  VariableProxy* NewVariableProxy(const AstString* name,
                                   bool is_this,
                                   Interface* interface = Interface::NewValue(),
                                   int position = RelocInfo::kNoPosition) {
@@ -3227,7 +3299,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(CallNew, call)
   }
 
-  CallRuntime* NewCallRuntime(Handle<String> name,
+  CallRuntime* NewCallRuntime(const AstString* name,
                               const Runtime::Function* function,
                               ZoneList<Expression*>* arguments,
                               int pos) {
@@ -3305,7 +3377,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
   }
 
   FunctionLiteral* NewFunctionLiteral(
-      Handle<String> name,
+      const AstString* name,
+      AstValueFactory* ast_value_factory,
       Scope* scope,
       ZoneList<Statement*>* body,
       int materialized_literal_count,
@@ -3319,7 +3392,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
       FunctionLiteral::IsGeneratorFlag is_generator,
       int position) {
     FunctionLiteral* lit = new(zone_) FunctionLiteral(
-        zone_, name, scope, body,
+        zone_, name, ast_value_factory, scope, body,
         materialized_literal_count, expected_property_count, handler_count,
         parameter_count, function_type, has_duplicate_parameters, is_function,
         is_parenthesized, is_generator, position);
@@ -3331,7 +3404,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
   }
 
   NativeFunctionLiteral* NewNativeFunctionLiteral(
-      Handle<String> name, v8::Extension* extension, int pos) {
+      const AstString* name, v8::Extension* extension,
+      int pos) {
     NativeFunctionLiteral* lit =
         new(zone_) NativeFunctionLiteral(zone_, name, extension, pos);
     VISIT_AND_RETURN(NativeFunctionLiteral, lit)
@@ -3347,6 +3421,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
  private:
   Zone* zone_;
   Visitor visitor_;
+  AstValueFactory* ast_value_factory_;
 };
 
 
index 42fcc78406bfa945b9902df124372bab36928235..cbd9be649a142d32a259000bd50ba8e0ec3378d1 100644 (file)
@@ -38,7 +38,8 @@ CompilationInfo::CompilationInfo(Handle<Script> script,
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL) {
   Initialize(script->GetIsolate(), BASE, zone);
 }
 
@@ -51,7 +52,8 @@ CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -66,7 +68,8 @@ CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -78,7 +81,8 @@ CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL) {
   Initialize(isolate, STUB, zone);
   code_stub_ = stub;
 }
@@ -131,6 +135,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
 CompilationInfo::~CompilationInfo() {
   delete deferred_handles_;
   delete no_frame_ranges_;
+  delete ast_value_factory_;
 #ifdef DEBUG
   // Check that no dependent maps have been added or added dependent maps have
   // been rolled back or committed.
index 6531474a17d28b24951373639a103d8206741c43..9d91b21bd3d4851b9141ebbd0b145a23087a82ac 100644 (file)
@@ -12,6 +12,7 @@
 namespace v8 {
 namespace internal {
 
+class AstValueFactory;
 class ScriptData;
 class HydrogenCodeStub;
 
@@ -321,6 +322,11 @@ class CompilationInfo {
 
   int optimization_id() const { return optimization_id_; }
 
+  AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
+  void SetAstValueFactory(AstValueFactory* ast_value_factory) {
+    ast_value_factory_ = ast_value_factory;
+  }
+
  protected:
   CompilationInfo(Handle<Script> script,
                   Zone* zone);
@@ -464,6 +470,8 @@ class CompilationInfo {
 
   int optimization_id_;
 
+  AstValueFactory* ast_value_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
 };
 
index a3c2f08ae7a34e23e3f909614dadc08e30a4009c..eef4af4843afad262212e6d0e5d87b06e84f65b9 100644 (file)
@@ -5,14 +5,16 @@
 #include "src/v8.h"
 
 #include "src/ast.h"
+#include "src/ast-value-factory.h"
 #include "src/func-name-inferrer.h"
 #include "src/list-inl.h"
 
 namespace v8 {
 namespace internal {
 
-FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
-    : isolate_(isolate),
+FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
+                                   Zone* zone)
+    : ast_value_factory_(ast_value_factory),
       entries_stack_(10, zone),
       names_stack_(5, zone),
       funcs_to_infer_(4, zone),
@@ -20,66 +22,119 @@ FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
 }
 
 
-void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
+void FuncNameInferrer::PushEnclosingName(const AstString* name) {
   // Enclosing name is a name of a constructor function. To check
   // that it is really a constructor, we check that it is not empty
   // and starts with a capital letter.
-  if (name->length() > 0 && Runtime::IsUpperCaseChar(
-          isolate()->runtime_state(), name->Get(0))) {
+  if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
     names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
   }
 }
 
 
-void FuncNameInferrer::PushLiteralName(Handle<String> name) {
-  if (IsOpen() &&
-      !String::Equals(isolate()->factory()->prototype_string(), name)) {
+void FuncNameInferrer::PushLiteralName(const AstString* name) {
+  if (IsOpen() && name != ast_value_factory_->prototype_string()) {
     names_stack_.Add(Name(name, kLiteralName), zone());
   }
 }
 
 
-void FuncNameInferrer::PushVariableName(Handle<String> name) {
-  if (IsOpen() &&
-      !String::Equals(isolate()->factory()->dot_result_string(), name)) {
+void FuncNameInferrer::PushVariableName(const AstString* name) {
+  if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
     names_stack_.Add(Name(name, kVariableName), zone());
   }
 }
 
 
-Handle<String> FuncNameInferrer::MakeNameFromStack() {
-  return MakeNameFromStackHelper(0, isolate()->factory()->empty_string());
-}
-
-
-Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
-                                                         Handle<String> prev) {
-  if (pos >= names_stack_.length()) return prev;
-  if (pos < names_stack_.length() - 1 &&
-      names_stack_.at(pos).type == kVariableName &&
-      names_stack_.at(pos + 1).type == kVariableName) {
-    // Skip consecutive variable declarations.
-    return MakeNameFromStackHelper(pos + 1, prev);
+const AstString* FuncNameInferrer::MakeNameFromStack() {
+  // First see how many names we will use.
+  int length = 0;
+  bool one_byte = true;
+  int pos = 0;
+  while (pos < names_stack_.length()) {
+    if (pos < names_stack_.length() - 1 &&
+        names_stack_.at(pos).type == kVariableName &&
+        names_stack_.at(pos + 1).type == kVariableName) {
+      // Skip consecutive variable declarations.
+      ++pos;
+      continue;
+    }
+    int cur_length = names_stack_.at(pos).name->length();
+    if (length + 1 + cur_length > String::kMaxLength) {
+      break;
+    }
+    if (length == 0) {
+      length = cur_length;
+    } else {  // Add the . between names.
+      length += (1 + cur_length);
+    }
+    one_byte = one_byte && names_stack_.at(pos).name->is_one_byte();
+    ++pos;
+  }
+  const AstString* to_return = NULL;
+  const char* dot = ".";
+  if (one_byte) {
+    Vector<uint8_t> new_name = Vector<uint8_t>::New(length);
+    int name_pos = 0;
+    for (int i = 0; i < pos; ++i) {
+      if (i < names_stack_.length() - 1 &&
+          names_stack_.at(i).type == kVariableName &&
+          names_stack_.at(i + 1).type == kVariableName) {
+        // Skip consecutive variable declarations.
+        continue;
+      }
+      if (name_pos != 0) {
+        CopyChars(new_name.start() + name_pos, dot, 1);
+        ++name_pos;
+      }
+      CopyChars(new_name.start() + name_pos,
+                names_stack_.at(i).name->raw_data(),
+                names_stack_.at(i).name->length());
+      name_pos += names_stack_.at(i).name->length();
+    }
+    to_return = ast_value_factory_->GetOneByteString(Vector<const uint8_t>(
+        reinterpret_cast<const uint8_t*>(new_name.start()),
+        new_name.length()));
+    new_name.Dispose();
   } else {
-    if (prev->length() > 0) {
-      Handle<String> name = names_stack_.at(pos).name;
-      if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
-      Factory* factory = isolate()->factory();
-      Handle<String> curr =
-          factory->NewConsString(factory->dot_string(), name).ToHandleChecked();
-      curr = factory->NewConsString(prev, curr).ToHandleChecked();
-      return MakeNameFromStackHelper(pos + 1, curr);
-    } else {
-      return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
+    Vector<uint16_t> new_name = Vector<uint16_t>::New(length);
+    int name_pos = 0;
+    for (int i = 0; i < pos; ++i) {
+      if (i < names_stack_.length() - 1 &&
+          names_stack_.at(i).type == kVariableName &&
+          names_stack_.at(i + 1).type == kVariableName) {
+        // Skip consecutive variable declarations.
+        continue;
+      }
+      if (name_pos != 0) {
+        CopyChars(new_name.start() + name_pos, dot, 1);
+        ++name_pos;
+      }
+      if (names_stack_.at(i).name->is_one_byte()) {
+        CopyChars(new_name.start() + name_pos,
+                  names_stack_.at(i).name->raw_data(),
+                  names_stack_.at(i).name->length());
+      } else {
+        CopyChars(new_name.start() + name_pos,
+                  reinterpret_cast<const uint16_t*>(
+                      names_stack_.at(i).name->raw_data()),
+                  names_stack_.at(i).name->length());
+      }
+      name_pos += names_stack_.at(i).name->length();
     }
+    to_return = ast_value_factory_->GetTwoByteString(Vector<const uint16_t>(
+        reinterpret_cast<const uint16_t*>(new_name.start()),
+        new_name.length()));
+    new_name.Dispose();
   }
+  return to_return;
 }
 
 
 void FuncNameInferrer::InferFunctionsNames() {
-  Handle<String> func_name = MakeNameFromStack();
+  const AstString* func_name = MakeNameFromStack();
   for (int i = 0; i < funcs_to_infer_.length(); ++i) {
-    funcs_to_infer_[i]->set_inferred_name(func_name);
+    funcs_to_infer_[i]->set_raw_inferred_name(func_name);
   }
   funcs_to_infer_.Rewind(0);
 }
index 0c5399c7bf1c10bfad14a0b86d7bf1e0f24da646..a590c4772d9dd0c0ab955a3aa330b2724a060e95 100644 (file)
@@ -11,8 +11,9 @@
 namespace v8 {
 namespace internal {
 
+class AstString;
+class AstValueFactory;
 class FunctionLiteral;
-class Isolate;
 
 // FuncNameInferrer is a stateful class that is used to perform name
 // inference for anonymous functions during static analysis of source code.
@@ -26,13 +27,13 @@ class Isolate;
 // a name.
 class FuncNameInferrer : public ZoneObject {
  public:
-  FuncNameInferrer(Isolate* isolate, Zone* zone);
+  FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
 
   // Returns whether we have entered name collection state.
   bool IsOpen() const { return !entries_stack_.is_empty(); }
 
   // Pushes an enclosing the name of enclosing function onto names stack.
-  void PushEnclosingName(Handle<String> name);
+  void PushEnclosingName(const AstString* name);
 
   // Enters name collection state.
   void Enter() {
@@ -40,9 +41,9 @@ class FuncNameInferrer : public ZoneObject {
   }
 
   // Pushes an encountered name onto names stack when in collection state.
-  void PushLiteralName(Handle<String> name);
+  void PushLiteralName(const AstString* name);
 
-  void PushVariableName(Handle<String> name);
+  void PushVariableName(const AstString* name);
 
   // Adds a function to infer name for.
   void AddFunction(FunctionLiteral* func_to_infer) {
@@ -80,24 +81,20 @@ class FuncNameInferrer : public ZoneObject {
     kVariableName
   };
   struct Name {
-    Name(Handle<String> name, NameType type) : name(name), type(type) { }
-    Handle<String> name;
+    Name(const AstString* name, NameType type) : name(name), type(type) {}
+    const AstString* name;
     NameType type;
   };
 
-  Isolate* isolate() { return isolate_; }
   Zone* zone() const { return zone_; }
 
   // Constructs a full name in dotted notation from gathered names.
-  Handle<String> MakeNameFromStack();
-
-  // A helper function for MakeNameFromStack.
-  Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
+  const AstString* MakeNameFromStack();
 
   // Performs name inferring for added functions.
   void InferFunctionsNames();
 
-  Isolate* isolate_;
+  AstValueFactory* ast_value_factory_;
   ZoneList<int> entries_stack_;
   ZoneList<Name> names_stack_;
   ZoneList<FunctionLiteral*> funcs_to_infer_;
index 87fe616f2b011716ca1bc1fc3bb802c0788f032a..63a05c73e49988c5aee31b8ad4447373219cc3a7 100644 (file)
@@ -277,16 +277,11 @@ namespace internal {
   V(constructor_string, "constructor")                                   \
   V(dot_result_string, ".result")                                        \
   V(dot_for_string, ".for.")                                             \
-  V(dot_iterable_string, ".iterable")                                    \
-  V(dot_iterator_string, ".iterator")                                    \
-  V(dot_generator_object_string, ".generator_object")                    \
   V(eval_string, "eval")                                                 \
   V(empty_string, "")                                                    \
   V(function_string, "function")                                         \
   V(length_string, "length")                                             \
-  V(module_string, "module")                                             \
   V(name_string, "name")                                                 \
-  V(native_string, "native")                                             \
   V(null_string, "null")                                                 \
   V(number_string, "number")                                             \
   V(Number_string, "Number")                                             \
@@ -312,7 +307,6 @@ namespace internal {
   V(private_api_string, "private_api")                                   \
   V(private_intern_string, "private_intern")                             \
   V(Date_string, "Date")                                                 \
-  V(this_string, "this")                                                 \
   V(to_string_string, "toString")                                        \
   V(char_at_string, "CharAt")                                            \
   V(undefined_string, "undefined")                                       \
@@ -335,19 +329,13 @@ namespace internal {
   V(cell_value_string, "%cell_value")                                    \
   V(function_class_string, "Function")                                   \
   V(illegal_argument_string, "illegal argument")                         \
-  V(MakeReferenceError_string, "MakeReferenceError")                     \
-  V(MakeSyntaxError_string, "MakeSyntaxError")                           \
-  V(MakeTypeError_string, "MakeTypeError")                               \
-  V(unknown_label_string, "unknown_label")                               \
   V(space_string, " ")                                                   \
   V(exec_string, "exec")                                                 \
   V(zero_string, "0")                                                    \
   V(global_eval_string, "GlobalEval")                                    \
   V(identity_hash_string, "v8::IdentityHash")                            \
   V(closure_string, "(closure)")                                         \
-  V(use_strict_string, "use strict")                                     \
   V(dot_string, ".")                                                     \
-  V(anonymous_function_string, "(anonymous function)")                   \
   V(compare_ic_string, "==")                                             \
   V(strict_compare_ic_string, "===")                                     \
   V(infinity_string, "Infinity")                                         \
index d6e84068e9a86de4fc4cf827ea2435b8c7b30b3c..f58dbc972131fc7b4f0a51c37aa1d5ebbe333760 100644 (file)
@@ -9,15 +9,6 @@
 namespace v8 {
 namespace internal {
 
-static bool Match(void* key1, void* key2) {
-  String* name1 = *static_cast<String**>(key1);
-  String* name2 = *static_cast<String**>(key2);
-  ASSERT(name1->IsInternalizedString());
-  ASSERT(name2->IsInternalizedString());
-  return name1 == name2;
-}
-
-
 Interface* Interface::Lookup(Handle<String> name, Zone* zone) {
   ASSERT(IsModule());
   ZoneHashMap* map = Chase()->exports_;
@@ -47,8 +38,8 @@ int Nesting::current_ = 0;
 #endif
 
 
-void Interface::DoAdd(
-    void* name, uint32_t hash, Interface* interface, Zone* zone, bool* ok) {
+void Interface::DoAdd(const void* name, uint32_t hash, Interface* interface,
+                      Zone* zone, bool* ok) {
   MakeModule(ok);
   if (!*ok) return;
 
@@ -57,8 +48,9 @@ void Interface::DoAdd(
     PrintF("%*s# Adding...\n", Nesting::current(), "");
     PrintF("%*sthis = ", Nesting::current(), "");
     this->Print(Nesting::current());
-    PrintF("%*s%s : ", Nesting::current(), "",
-           (*static_cast<String**>(name))->ToAsciiArray());
+    const AstString* symbol = static_cast<const AstString*>(name);
+    PrintF("%*s%.*s : ", Nesting::current(), "", symbol->length(),
+           symbol->raw_data());
     interface->Print(Nesting::current());
   }
 #endif
@@ -68,10 +60,12 @@ void Interface::DoAdd(
 
   if (*map == NULL) {
     *map = new(zone->New(sizeof(ZoneHashMap)))
-        ZoneHashMap(Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
+        ZoneHashMap(ZoneHashMap::PointersMatch,
+                    ZoneHashMap::kDefaultHashMapCapacity, allocator);
   }
 
-  ZoneHashMap::Entry* p = (*map)->Lookup(name, hash, !IsFrozen(), allocator);
+  ZoneHashMap::Entry* p =
+      (*map)->Lookup(const_cast<void*>(name), hash, !IsFrozen(), allocator);
   if (p == NULL) {
     // This didn't have name but was frozen already, that's an error.
     *ok = false;
index 086facf6665b1d189c24914d9a62a1d564e22133..f79274ef7fe6e24582133757995348841786f2fb 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef V8_INTERFACE_H_
 #define V8_INTERFACE_H_
 
+#include "src/ast-value-factory.h"
 #include "src/zone-inl.h"  // For operator new.
 
 namespace v8 {
@@ -59,8 +60,9 @@ class Interface : public ZoneObject {
 
   // Add a name to the list of exports. If it already exists, unify with
   // interface, otherwise insert unless this is closed.
-  void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) {
-    DoAdd(name.location(), name->Hash(), interface, zone, ok);
+  void Add(const AstString* name, Interface* interface, Zone* zone,
+           bool* ok) {
+    DoAdd(name, name->hash(), interface, zone, ok);
   }
 
   // Unify with another interface. If successful, both interface objects will
@@ -146,9 +148,9 @@ class Interface : public ZoneObject {
   class Iterator {
    public:
     bool done() const { return entry_ == NULL; }
-    Handle<String> name() const {
+    const AstString* name() const {
       ASSERT(!done());
-      return Handle<String>(*static_cast<String**>(entry_->key));
+      return static_cast<const AstString*>(entry_->key);
     }
     Interface* interface() const {
       ASSERT(!done());
@@ -207,7 +209,7 @@ class Interface : public ZoneObject {
     return result;
   }
 
-  void DoAdd(void* name, uint32_t hash, Interface* interface, Zone* zone,
+  void DoAdd(const void* name, uint32_t hash, Interface* interface, Zone* zone,
              bool* ok);
   void DoUnify(Interface* that, bool* ok, Zone* zone);
 };
index 8c983e4251bbfda06fd0b009d067ee0fc30d6177..63fb13be99739d6344726f3882629bf44d955240 100644 (file)
@@ -1716,22 +1716,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
 
 
 bool HeapNumber::HeapNumberBooleanValue() {
-  // NaN, +0, and -0 should return the false object
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  union IeeeDoubleLittleEndianArchType u;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  union IeeeDoubleBigEndianArchType u;
-#endif
-  u.d = value();
-  if (u.bits.exp == 2047) {
-    // Detect NaN for IEEE double precision floating point.
-    if ((u.bits.man_low | u.bits.man_high) != 0) return false;
-  }
-  if (u.bits.exp == 0) {
-    // Detect +0, and -0 for IEEE double precision floating point.
-    if ((u.bits.man_low | u.bits.man_high) == 0) return false;
-  }
-  return true;
+  return DoubleToBoolean(value());
 }
 
 
@@ -9352,29 +9337,7 @@ bool String::ComputeArrayIndex(uint32_t* index) {
   if (length == 0 || length > kMaxArrayIndexSize) return false;
   ConsStringIteratorOp op;
   StringCharacterStream stream(this, &op);
-  uint16_t ch = stream.GetNext();
-
-  // If the string begins with a '0' character, it must only consist
-  // of it to be a legal array index.
-  if (ch == '0') {
-    *index = 0;
-    return length == 1;
-  }
-
-  // Convert string to uint32 array index; character by character.
-  int d = ch - '0';
-  if (d < 0 || d > 9) return false;
-  uint32_t result = d;
-  while (stream.HasMore()) {
-    d = stream.GetNext() - '0';
-    if (d < 0 || d > 9) return false;
-    // Check that the new result is below the 32 bit limit.
-    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
-    result = (result * 10) + d;
-  }
-
-  *index = result;
-  return true;
+  return StringToArrayIndex(&stream, index);
 }
 
 
index 9bca3d552401b93770765c2c0bcc390655050715..722ed8beaf470288df7de99157ea58a191ec7c23 100644 (file)
@@ -326,7 +326,9 @@ unsigned* ScriptData::ReadAddress(int position) const {
 
 
 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
-  Scope* result = new(zone()) Scope(parent, scope_type, zone());
+  ASSERT(ast_value_factory_);
+  Scope* result =
+      new (zone()) Scope(parent, scope_type, ast_value_factory_, zone());
   result->Initialize();
   return result;
 }
@@ -399,10 +401,9 @@ class TargetScope BASE_EMBEDDED {
 // ----------------------------------------------------------------------------
 // Implementation of Parser
 
-bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
-  Factory* factory = parser_->isolate()->factory();
-  return identifier.is_identical_to(factory->eval_string())
-      || identifier.is_identical_to(factory->arguments_string());
+bool ParserTraits::IsEvalOrArguments(const AstString* identifier) const {
+  return identifier == parser_->ast_value_factory_->eval_string() ||
+         identifier == parser_->ast_value_factory_->arguments_string();
 }
 
 
@@ -424,10 +425,10 @@ bool ParserTraits::IsIdentifier(Expression* expression) {
 void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
                                     Expression* expression) {
   if (expression->IsPropertyName()) {
-    fni->PushLiteralName(expression->AsLiteral()->AsPropertyName());
+    fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
   } else {
     fni->PushLiteralName(
-        parser_->isolate()->factory()->anonymous_function_string());
+        parser_->ast_value_factory_->anonymous_function_string());
   }
 }
 
@@ -446,7 +447,7 @@ void ParserTraits::CheckPossibleEvalCall(Expression* expression,
                                          Scope* scope) {
   VariableProxy* callee = expression->AsVariableProxy();
   if (callee != NULL &&
-      callee->IsVariable(parser_->isolate()->factory()->eval_string())) {
+      callee->raw_name() == parser_->ast_value_factory_->eval_string()) {
     scope->DeclarationScope()->RecordEvalCall();
   }
 }
@@ -464,10 +465,10 @@ Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
 bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
     Expression** x, Expression* y, Token::Value op, int pos,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() &&
-      y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
-    double x_val = (*x)->AsLiteral()->value()->Number();
-    double y_val = y->AsLiteral()->value()->Number();
+  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
+      y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
+    double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
+    double y_val = y->AsLiteral()->raw_value()->AsNumber();
     switch (op) {
       case Token::ADD:
         *x = factory->NewNumberLiteral(x_val + y_val, pos);
@@ -526,16 +527,14 @@ Expression* ParserTraits::BuildUnaryExpression(
     AstNodeFactory<AstConstructionVisitor>* factory) {
   ASSERT(expression != NULL);
   if (expression->IsLiteral()) {
-    Handle<Object> literal = expression->AsLiteral()->value();
+    const AstValue* literal = expression->AsLiteral()->raw_value();
     if (op == Token::NOT) {
       // Convert the literal to a boolean condition and negate it.
       bool condition = literal->BooleanValue();
-      Handle<Object> result =
-          parser_->isolate()->factory()->ToBoolean(!condition);
-      return factory->NewLiteral(result, pos);
+      return factory->NewBooleanLiteral(!condition, pos);
     } else if (literal->IsNumber()) {
       // Compute some expressions involving only number literals.
-      double value = literal->Number();
+      double value = literal->AsNumber();
       switch (op) {
         case Token::ADD:
           return expression;
@@ -569,51 +568,41 @@ Expression* ParserTraits::BuildUnaryExpression(
 
 Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
   return NewThrowError(
-      parser_->isolate()->factory()->MakeReferenceError_string(),
-      message, HandleVector<Object>(NULL, 0), pos);
+      parser_->ast_value_factory_->make_reference_error_string(), message, NULL,
+      pos);
 }
 
 
 Expression* ParserTraits::NewThrowSyntaxError(
-    const char* message, Handle<Object> arg, int pos) {
-  int argc = arg.is_null() ? 0 : 1;
-  Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
-  return NewThrowError(
-      parser_->isolate()->factory()->MakeSyntaxError_string(),
-      message, arguments, pos);
+    const char* message, const AstString* arg, int pos) {
+  return NewThrowError(parser_->ast_value_factory_->make_syntax_error_string(),
+                       message, arg, pos);
 }
 
 
 Expression* ParserTraits::NewThrowTypeError(
-    const char* message, Handle<Object> arg, int pos) {
-  int argc = arg.is_null() ? 0 : 1;
-  Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
-  return NewThrowError(
-      parser_->isolate()->factory()->MakeTypeError_string(),
-      message, arguments, pos);
+    const char* message, const AstString* arg, int pos) {
+  return NewThrowError(parser_->ast_value_factory_->make_type_error_string(),
+                       message, arg, pos);
 }
 
 
 Expression* ParserTraits::NewThrowError(
-    Handle<String> constructor, const char* message,
-    Vector<Handle<Object> > arguments, int pos) {
+    const AstString* constructor, const char* message,
+    const AstString* arg, int pos) {
   Zone* zone = parser_->zone();
-  Factory* factory = parser_->isolate()->factory();
-  int argc = arguments.length();
-  Handle<FixedArray> elements = factory->NewFixedArray(argc, TENURED);
-  for (int i = 0; i < argc; i++) {
-    Handle<Object> element = arguments[i];
-    if (!element.is_null()) {
-      elements->set(i, *element);
-    }
-  }
-  Handle<JSArray> array =
-      factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
-
-  ZoneList<Expression*>* args = new(zone) ZoneList<Expression*>(2, zone);
-  Handle<String> type = factory->InternalizeUtf8String(message);
-  args->Add(parser_->factory()->NewLiteral(type, pos), zone);
-  args->Add(parser_->factory()->NewLiteral(array, pos), zone);
+  int argc = arg != NULL ? 1 : 0;
+  const AstString* type =
+      parser_->ast_value_factory_->GetOneByteString(Vector<const uint8_t>(
+          reinterpret_cast<const uint8_t*>(message), StrLength(message)));
+  ZoneList<const AstString*>* array =
+      new (zone) ZoneList<const AstString*>(argc, zone);
+  if (arg != NULL) {
+    array->Add(arg, zone);
+  }
+  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+  args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
+  args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
   CallRuntime* call_constructor =
       parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
   return parser_->factory()->NewThrow(call_constructor, pos);
@@ -634,13 +623,21 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
   parser_->pending_error_location_ = source_location;
   parser_->pending_error_message_ = message;
   parser_->pending_error_char_arg_ = arg;
-  parser_->pending_error_arg_ = Handle<String>();
+  parser_->pending_error_arg_ = NULL;
   parser_->pending_error_is_reference_error_ = is_reference_error;
 }
 
 
 void ParserTraits::ReportMessage(const char* message,
-                                 MaybeHandle<String> arg,
+                                 const char* arg,
+                                 bool is_reference_error) {
+  Scanner::Location source_location = parser_->scanner()->location();
+  ReportMessageAt(source_location, message, arg, is_reference_error);
+}
+
+
+void ParserTraits::ReportMessage(const char* message,
+                                 const AstString* arg,
                                  bool is_reference_error) {
   Scanner::Location source_location = parser_->scanner()->location();
   ReportMessageAt(source_location, message, arg, is_reference_error);
@@ -649,7 +646,7 @@ void ParserTraits::ReportMessage(const char* message,
 
 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                    const char* message,
-                                   MaybeHandle<String> arg,
+                                   const AstString* arg,
                                    bool is_reference_error) {
   if (parser_->stack_overflow()) {
     // Suppress the error message (syntax error or such) in the presence of a
@@ -666,17 +663,16 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
 }
 
 
-Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
-  Handle<String> result =
-      parser_->scanner()->AllocateInternalizedString(parser_->isolate());
-  ASSERT(!result.is_null());
+const AstString* ParserTraits::GetSymbol(Scanner* scanner) {
+  const AstString* result =
+      parser_->scanner()->CurrentSymbol(parser_->ast_value_factory_);
+  ASSERT(result != NULL);
   return result;
 }
 
 
-Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
-                                               PretenureFlag tenured) {
-  return scanner->AllocateNextLiteralString(parser_->isolate(), tenured);
+const AstString* ParserTraits::GetNextSymbol(Scanner* scanner) {
+  return parser_->scanner()->NextSymbol(parser_->ast_value_factory_);
 }
 
 
@@ -691,14 +687,13 @@ Literal* ParserTraits::ExpressionFromLiteral(
     Token::Value token, int pos,
     Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  Factory* isolate_factory = parser_->isolate()->factory();
   switch (token) {
     case Token::NULL_LITERAL:
-      return factory->NewLiteral(isolate_factory->null_value(), pos);
+      return factory->NewNullLiteral(pos);
     case Token::TRUE_LITERAL:
-      return factory->NewLiteral(isolate_factory->true_value(), pos);
+      return factory->NewBooleanLiteral(true, pos);
     case Token::FALSE_LITERAL:
-      return factory->NewLiteral(isolate_factory->false_value(), pos);
+      return factory->NewBooleanLiteral(false, pos);
     case Token::NUMBER: {
       double value = scanner->DoubleValue();
       return factory->NewNumberLiteral(value, pos);
@@ -711,13 +706,13 @@ Literal* ParserTraits::ExpressionFromLiteral(
 
 
 Expression* ParserTraits::ExpressionFromIdentifier(
-    Handle<String> name, int pos, Scope* scope,
+    const AstString* name, int pos, Scope* scope,
     AstNodeFactory<AstConstructionVisitor>* factory) {
   if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
   // The name may refer to a module instance object, so its type is unknown.
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Variable %s ", name->ToAsciiArray());
+    PrintF("# Variable %.*s ", name->length(), name->raw_data());
 #endif
   Interface* interface = Interface::NewUnknown(parser_->zone());
   return scope->NewUnresolved(factory, name, interface, pos);
@@ -727,16 +722,15 @@ Expression* ParserTraits::ExpressionFromIdentifier(
 Expression* ParserTraits::ExpressionFromString(
     int pos, Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  Handle<String> symbol = GetSymbol(scanner);
+  const AstString* symbol = GetSymbol(scanner);
   if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
-  return factory->NewLiteral(symbol, pos);
+  return factory->NewStringLiteral(symbol, pos);
 }
 
 
 Literal* ParserTraits::GetLiteralTheHole(
     int position, AstNodeFactory<AstConstructionVisitor>* factory) {
-  return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
-                             RelocInfo::kNoPosition);
+  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
 }
 
 
@@ -746,7 +740,7 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
 
 
 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
-    Handle<String> name,
+    const AstString* name,
     Scanner::Location function_name_location,
     bool name_is_strict_reserved,
     bool is_generator,
@@ -774,9 +768,11 @@ Parser::Parser(CompilationInfo* info)
       target_stack_(NULL),
       cached_data_(NULL),
       cached_data_mode_(NO_CACHED_DATA),
+      ast_value_factory_(NULL),
       info_(info),
       has_pending_error_(false),
       pending_error_message_(NULL),
+      pending_error_arg_(NULL),
       pending_error_char_arg_(NULL) {
   ASSERT(!script_.is_null());
   isolate_->set_ast_node_id(0);
@@ -800,7 +796,7 @@ FunctionLiteral* Parser::ParseProgram() {
   if (FLAG_trace_parse) {
     timer.Start();
   }
-  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
+  fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
 
   // Initialize parser state.
   CompleteParserRecorder recorder;
@@ -855,13 +851,16 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
   ASSERT(scope_ == NULL);
   ASSERT(target_stack_ == NULL);
 
-  Handle<String> no_name = isolate()->factory()->empty_string();
-
   FunctionLiteral* result = NULL;
   { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
     info->SetGlobalScope(scope);
     if (!info->context().is_null()) {
       scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
+      // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
+      // means the Parser cannot operate independent of the V8 heap. Tell the
+      // string table to internalize strings and values right after they're
+      // created.
+      ast_value_factory_->Internalize(isolate());
     }
     original_scope_ = scope;
     if (info->is_eval()) {
@@ -884,7 +883,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
     ParsingModeScope parsing_mode(this, mode);
 
     // Enters 'scope'.
-    FunctionState function_state(&function_state_, &scope_, scope, zone());
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
 
     scope_->SetStrictMode(info->strict_mode());
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -911,7 +911,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
 
     if (ok) {
       result = factory()->NewFunctionLiteral(
-          no_name,
+          ast_value_factory_->empty_string(),
+          ast_value_factory_,
           scope_,
           body,
           function_state.materialized_literal_count(),
@@ -983,8 +984,10 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
   ASSERT(target_stack_ == NULL);
 
   Handle<String> name(String::cast(shared_info->name()));
-  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
-  fni_->PushEnclosingName(name);
+  ASSERT(ast_value_factory_);
+  fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
+  const AstString* raw_name = ast_value_factory_->GetString(name);
+  fni_->PushEnclosingName(raw_name);
 
   ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
 
@@ -1000,7 +1003,8 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
                                            zone());
     }
     original_scope_ = scope;
-    FunctionState function_state(&function_state_, &scope_, scope, zone());
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
     ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
     ASSERT(info()->strict_mode() == shared_info->strict_mode());
     scope->SetStrictMode(shared_info->strict_mode());
@@ -1010,7 +1014,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
               : FunctionLiteral::NAMED_EXPRESSION)
         : FunctionLiteral::DECLARATION;
     bool ok = true;
-    result = ParseFunctionLiteral(name,
+    result = ParseFunctionLiteral(raw_name,
                                   Scanner::Location::invalid(),
                                   false,  // Strict mode name already checked.
                                   shared_info->is_generator(),
@@ -1079,15 +1083,12 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
       // Still processing directive prologue?
       if ((e_stat = stat->AsExpressionStatement()) != NULL &&
           (literal = e_stat->expression()->AsLiteral()) != NULL &&
-          literal->value()->IsString()) {
-        Handle<String> directive = Handle<String>::cast(literal->value());
-
+          literal->raw_value()->IsString()) {
         // Check "use strict" directive (ES5 14.1).
         if (strict_mode() == SLOPPY &&
-            String::Equals(isolate()->factory()->use_strict_string(),
-                           directive) &&
-            token_loc.end_pos - token_loc.beg_pos ==
-              isolate()->heap()->use_strict_string()->length() + 2) {
+            literal->raw_value()->AsString() ==
+                ast_value_factory_->use_strict_string() &&
+            token_loc.end_pos - token_loc.beg_pos == 12) {
           // TODO(mstarzinger): Global strict eval calls, need their own scope
           // as specified in ES5 10.4.2(3). The correct fix would be to always
           // add this scope in DoParseProgram(), but that requires adaptations
@@ -1118,7 +1119,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
 }
 
 
-Statement* Parser::ParseModuleElement(ZoneStringList* labels,
+Statement* Parser::ParseModuleElement(ZoneList<const AstString*>* labels,
                                       bool* ok) {
   // (Ecma 262 5th Edition, clause 14):
   // SourceElement:
@@ -1152,10 +1153,9 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
           !scanner()->HasAnyLineTerminatorBeforeNext() &&
           stmt != NULL) {
         ExpressionStatement* estmt = stmt->AsExpressionStatement();
-        if (estmt != NULL &&
-            estmt->expression()->AsVariableProxy() != NULL &&
-            String::Equals(isolate()->factory()->module_string(),
-                           estmt->expression()->AsVariableProxy()->name()) &&
+        if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
+            estmt->expression()->AsVariableProxy()->raw_name() ==
+                ast_value_factory_->module_string() &&
             !scanner()->literal_contains_escapes()) {
           return ParseModuleDeclaration(NULL, ok);
         }
@@ -1166,16 +1166,17 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
 }
 
 
-Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseModuleDeclaration(ZoneList<const AstString*>* names,
+                                          bool* ok) {
   // ModuleDeclaration:
   //    'module' Identifier Module
 
   int pos = peek_position();
-  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+  const AstString* name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
 
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module %s...\n", name->ToAsciiArray());
+    PrintF("# Module %.*s ", name->length(), name->raw_data());
 #endif
 
   Module* module = ParseModule(CHECK_OK);
@@ -1186,10 +1187,9 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
 
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module %s.\n", name->ToAsciiArray());
-
+    PrintF("# Module %.*s ", name->length(), name->raw_data());
   if (FLAG_print_interfaces) {
-    PrintF("module %s : ", name->ToAsciiArray());
+    PrintF("module %.*s: ", name->length(), name->raw_data());
     module->interface()->Print();
   }
 #endif
@@ -1290,17 +1290,17 @@ Module* Parser::ParseModulePath(bool* ok) {
   int pos = peek_position();
   Module* result = ParseModuleVariable(CHECK_OK);
   while (Check(Token::PERIOD)) {
-    Handle<String> name = ParseIdentifierName(CHECK_OK);
+    const AstString* name = ParseIdentifierName(CHECK_OK);
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Path .%s ", name->ToAsciiArray());
+      PrintF("# Path .%.*s ", name->length(), name->raw_data());
 #endif
     Module* member = factory()->NewModulePath(result, name, pos);
     result->interface()->Add(name, member->interface(), zone(), ok);
     if (!*ok) {
 #ifdef DEBUG
       if (FLAG_print_interfaces) {
-        PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
+        PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
         PrintF("result: ");
         result->interface()->Print();
         PrintF("member: ");
@@ -1322,10 +1322,10 @@ Module* Parser::ParseModuleVariable(bool* ok) {
   //    Identifier
 
   int pos = peek_position();
-  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+  const AstString* name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module variable %s ", name->ToAsciiArray());
+    PrintF("# Module variable %.*s ", name->length(), name->raw_data());
 #endif
   VariableProxy* proxy = scope_->NewUnresolved(
       factory(), name, Interface::NewModule(zone()),
@@ -1341,7 +1341,7 @@ Module* Parser::ParseModuleUrl(bool* ok) {
 
   int pos = peek_position();
   Expect(Token::STRING, CHECK_OK);
-  Handle<String> symbol = GetSymbol();
+  const AstString* symbol = GetSymbol(scanner());
 
   // TODO(ES6): Request JS resource from environment...
 
@@ -1385,9 +1385,9 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
 
   int pos = peek_position();
   Expect(Token::IMPORT, CHECK_OK);
-  ZoneStringList names(1, zone());
+  ZoneList<const AstString*> names(1, zone());
 
-  Handle<String> name = ParseIdentifierName(CHECK_OK);
+  const AstString* name = ParseIdentifierName(CHECK_OK);
   names.Add(name, zone());
   while (peek() == Token::COMMA) {
     Consume(Token::COMMA);
@@ -1405,14 +1405,15 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
   for (int i = 0; i < names.length(); ++i) {
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Import %s ", names[i]->ToAsciiArray());
+      PrintF("# Import %.*s ", name->length(), name->raw_data());
 #endif
     Interface* interface = Interface::NewUnknown(zone());
     module->interface()->Add(names[i], interface, zone(), ok);
     if (!*ok) {
 #ifdef DEBUG
       if (FLAG_print_interfaces) {
-        PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
+        PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
+               name->raw_data());
         PrintF("module: ");
         module->interface()->Print();
       }
@@ -1443,14 +1444,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
   Expect(Token::EXPORT, CHECK_OK);
 
   Statement* result = NULL;
-  ZoneStringList names(1, zone());
+  ZoneList<const AstString*> names(1, zone());
   switch (peek()) {
     case Token::IDENTIFIER: {
       int pos = position();
-      Handle<String> name =
+      const AstString* name =
           ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
       // Handle 'module' as a context-sensitive keyword.
-      if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
+      if (name != ast_value_factory_->module_string()) {
         names.Add(name, zone());
         while (peek() == Token::COMMA) {
           Consume(Token::COMMA);
@@ -1486,7 +1487,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
   for (int i = 0; i < names.length(); ++i) {
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Export %s ", names[i]->ToAsciiArray());
+      PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
 #endif
     Interface* inner = Interface::NewUnknown(zone());
     interface->Add(names[i], inner, zone(), CHECK_OK);
@@ -1506,7 +1507,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
 }
 
 
-Statement* Parser::ParseBlockElement(ZoneStringList* labels,
+Statement* Parser::ParseBlockElement(ZoneList<const AstString*>* labels,
                                      bool* ok) {
   // (Ecma 262 5th Edition, clause 14):
   // SourceElement:
@@ -1531,7 +1532,8 @@ Statement* Parser::ParseBlockElement(ZoneStringList* labels,
 }
 
 
-Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseStatement(ZoneList<const AstString*>* labels,
+                                  bool* ok) {
   // Statement ::
   //   Block
   //   VariableStatement
@@ -1641,8 +1643,8 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
 }
 
 
-VariableProxy* Parser::NewUnresolved(
-    Handle<String> name, VariableMode mode, Interface* interface) {
+VariableProxy* Parser::NewUnresolved(const AstString* name, VariableMode mode,
+                                     Interface* interface) {
   // If we are inside a function, a declaration of a var/const variable is a
   // truly local variable, and the scope of the variable is always the function
   // scope.
@@ -1655,7 +1657,8 @@ VariableProxy* Parser::NewUnresolved(
 
 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
   VariableProxy* proxy = declaration->proxy();
-  Handle<String> name = proxy->name();
+  ASSERT(proxy->raw_name() != NULL);
+  const AstString* name = proxy->raw_name();
   VariableMode mode = declaration->mode();
   Scope* declaration_scope = DeclarationScope(mode);
   Variable* var = NULL;
@@ -1783,8 +1786,10 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
     if (FLAG_harmony_modules) {
       bool ok;
 #ifdef DEBUG
-      if (FLAG_print_interface_details)
-        PrintF("# Declare %s\n", var->name()->ToAsciiArray());
+      if (FLAG_print_interface_details) {
+        PrintF("# Declare %.*s ", var->raw_name()->length(),
+               var->raw_name()->raw_data());
+      }
 #endif
       proxy->interface()->Unify(var->interface(), zone(), &ok);
       if (!ok) {
@@ -1812,7 +1817,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
   int pos = peek_position();
   Expect(Token::FUNCTION, CHECK_OK);
   // Allow "eval" or "arguments" for backward compatibility.
-  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+  const AstString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
   bool done = (peek() == Token::RPAREN);
   while (!done) {
@@ -1847,7 +1852,8 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
 }
 
 
-Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseFunctionDeclaration(ZoneList<const AstString*>* names,
+                                            bool* ok) {
   // FunctionDeclaration ::
   //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
   // GeneratorDeclaration ::
@@ -1857,7 +1863,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
   int pos = position();
   bool is_generator = allow_generators() && Check(Token::MUL);
   bool is_strict_reserved = false;
-  Handle<String> name = ParseIdentifierOrStrictReservedWord(
+  const AstString* name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
   FunctionLiteral* fun = ParseFunctionLiteral(name,
                                               scanner()->location(),
@@ -1883,7 +1889,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
 }
 
 
-Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseBlock(ZoneList<const AstString*>* labels, bool* ok) {
   if (allow_harmony_scoping() && strict_mode() == STRICT) {
     return ParseScopedBlock(labels, ok);
   }
@@ -1910,7 +1916,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
 }
 
 
-Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseScopedBlock(ZoneList<const AstString*>* labels, bool* ok) {
   // The harmony mode uses block elements instead of statements.
   //
   // Block ::
@@ -1945,12 +1951,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
 
 
 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
-                                      ZoneStringList* names,
+                                      ZoneList<const AstString*>* names,
                                       bool* ok) {
   // VariableStatement ::
   //   VariableDeclarations ';'
 
-  Handle<String> ignore;
+  const AstString* ignore;
   Block* result =
       ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
@@ -1966,8 +1972,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
 Block* Parser::ParseVariableDeclarations(
     VariableDeclarationContext var_context,
     VariableDeclarationProperties* decl_props,
-    ZoneStringList* names,
-    Handle<String>* out,
+    ZoneList<const AstString*>* names,
+    const AstString** out,
     bool* ok) {
   // VariableDeclarations ::
   //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
@@ -2075,7 +2081,7 @@ Block* Parser::ParseVariableDeclarations(
   // Create new block with one expected declaration.
   Block* block = factory()->NewBlock(NULL, 1, true, pos);
   int nvars = 0;  // the number of variables declared
-  Handle<String> name;
+  const AstString* name = NULL;
   do {
     if (fni_ != NULL) fni_->Enter();
 
@@ -2194,7 +2200,7 @@ Block* Parser::ParseVariableDeclarations(
       ZoneList<Expression*>* arguments =
           new(zone()) ZoneList<Expression*>(3, zone());
       // We have at least 1 parameter.
-      arguments->Add(factory()->NewLiteral(name, pos), zone());
+      arguments->Add(factory()->NewStringLiteral(name, pos), zone());
       CallRuntime* initialize;
 
       if (is_const) {
@@ -2206,7 +2212,7 @@ Block* Parser::ParseVariableDeclarations(
         // Note that the function does different things depending on
         // the number of arguments (1 or 2).
         initialize = factory()->NewCallRuntime(
-            isolate()->factory()->InitializeConstGlobal_string(),
+            ast_value_factory_->initialize_const_global_string(),
             Runtime::FunctionForId(Runtime::kHiddenInitializeConstGlobal),
             arguments, pos);
       } else {
@@ -2229,7 +2235,7 @@ Block* Parser::ParseVariableDeclarations(
         // Note that the function does different things depending on
         // the number of arguments (2 or 3).
         initialize = factory()->NewCallRuntime(
-            isolate()->factory()->InitializeVarGlobal_string(),
+            ast_value_factory_->initialize_var_global_string(),
             Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
             arguments, pos);
       }
@@ -2285,11 +2291,12 @@ Block* Parser::ParseVariableDeclarations(
 }
 
 
-static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
-  ASSERT(!label.is_null());
+static bool ContainsLabel(ZoneList<const AstString*>* labels,
+                          const AstString* label) {
+  ASSERT(label != NULL);
   if (labels != NULL) {
     for (int i = labels->length(); i-- > 0; ) {
-      if (labels->at(i).is_identical_to(label)) {
+      if (labels->at(i) == label) {
         return true;
       }
     }
@@ -2298,8 +2305,8 @@ static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
 }
 
 
-Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
-                                                      bool* ok) {
+Statement* Parser::ParseExpressionOrLabelledStatement(
+    ZoneList<const AstString*>* labels, bool* ok) {
   // ExpressionStatement | LabelledStatement ::
   //   Expression ';'
   //   Identifier ':' Statement
@@ -2312,7 +2319,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
     // Expression is a single identifier, and not, e.g., a parenthesized
     // identifier.
     VariableProxy* var = expr->AsVariableProxy();
-    Handle<String> label = var->name();
+    const AstString* label = var->raw_name();
     // TODO(1240780): We don't check for redeclaration of labels
     // during preparsing since keeping track of the set of active
     // labels requires nontrivial changes to the way scopes are
@@ -2324,7 +2331,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
       return NULL;
     }
     if (labels == NULL) {
-      labels = new(zone()) ZoneStringList(4, zone());
+      labels = new(zone()) ZoneList<const AstString*>(4, zone());
     }
     labels->Add(label, zone());
     // Remove the "ghost" variable that turned out to be a label
@@ -2343,8 +2350,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
       !scanner()->HasAnyLineTerminatorBeforeNext() &&
       expr != NULL &&
       expr->AsVariableProxy() != NULL &&
-      String::Equals(isolate()->factory()->native_string(),
-                     expr->AsVariableProxy()->name()) &&
+      expr->AsVariableProxy()->raw_name() ==
+          ast_value_factory_->native_string() &&
       !scanner()->literal_contains_escapes()) {
     return ParseNativeDeclaration(ok);
   }
@@ -2355,8 +2362,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
       peek() != Token::IDENTIFIER ||
       scanner()->HasAnyLineTerminatorBeforeNext() ||
       expr->AsVariableProxy() == NULL ||
-      !String::Equals(isolate()->factory()->module_string(),
-                      expr->AsVariableProxy()->name()) ||
+      expr->AsVariableProxy()->raw_name() !=
+          ast_value_factory_->module_string() ||
       scanner()->literal_contains_escapes()) {
     ExpectSemicolon(CHECK_OK);
   }
@@ -2364,7 +2371,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
 }
 
 
-IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
+IfStatement* Parser::ParseIfStatement(ZoneList<const AstString*>* labels,
+                                      bool* ok) {
   // IfStatement ::
   //   'if' '(' Expression ')' Statement ('else' Statement)?
 
@@ -2392,19 +2400,18 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
 
   int pos = peek_position();
   Expect(Token::CONTINUE, CHECK_OK);
-  Handle<String> label = Handle<String>::null();
+  const AstString* label = NULL;
   Token::Value tok = peek();
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
     // ECMA allows "eval" or "arguments" as labels even in strict mode.
     label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   }
-  IterationStatement* target = NULL;
-  target = LookupContinueTarget(label, CHECK_OK);
+  IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
   if (target == NULL) {
     // Illegal continue statement.
     const char* message = "illegal_continue";
-    if (!label.is_null()) {
+    if (label != NULL) {
       message = "unknown_label";
     }
     ParserTraits::ReportMessage(message, label);
@@ -2416,13 +2423,14 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
 }
 
 
-Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseBreakStatement(ZoneList<const AstString*>* labels,
+                                       bool* ok) {
   // BreakStatement ::
   //   'break' Identifier? ';'
 
   int pos = peek_position();
   Expect(Token::BREAK, CHECK_OK);
-  Handle<String> label;
+  const AstString* label = NULL;
   Token::Value tok = peek();
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
@@ -2431,7 +2439,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
   }
   // Parse labeled break statements that target themselves into
   // empty statements, e.g. 'l1: l2: l3: break l2;'
-  if (!label.is_null() && ContainsLabel(labels, label)) {
+  if (label != NULL && ContainsLabel(labels, label)) {
     ExpectSemicolon(CHECK_OK);
     return factory()->NewEmptyStatement(pos);
   }
@@ -2440,7 +2448,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
   if (target == NULL) {
     // Illegal break statement.
     const char* message = "illegal_break";
-    if (!label.is_null()) {
+    if (label != NULL) {
       message = "unknown_label";
     }
     ParserTraits::ReportMessage(message, label);
@@ -2494,7 +2502,8 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
 }
 
 
-Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseWithStatement(ZoneList<const AstString*>* labels,
+                                      bool* ok) {
   // WithStatement ::
   //   'with' '(' Expression ')' Statement
 
@@ -2556,8 +2565,8 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
 }
 
 
-SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
-                                              bool* ok) {
+SwitchStatement* Parser::ParseSwitchStatement(
+    ZoneList<const AstString*>* labels, bool* ok) {
   // SwitchStatement ::
   //   'switch' '(' Expression ')' '{' CaseClause* '}'
 
@@ -2640,7 +2649,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
   Scope* catch_scope = NULL;
   Variable* catch_variable = NULL;
   Block* catch_block = NULL;
-  Handle<String> name;
+  const AstString* name = NULL;
   if (tok == Token::CATCH) {
     Consume(Token::CATCH);
 
@@ -2710,8 +2719,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
 }
 
 
-DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
-                                                bool* ok) {
+DoWhileStatement* Parser::ParseDoWhileStatement(
+    ZoneList<const AstString*>* labels, bool* ok) {
   // DoStatement ::
   //   'do' Statement 'while' '(' Expression ')' ';'
 
@@ -2738,7 +2747,8 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
 }
 
 
-WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
+WhileStatement* Parser::ParseWhileStatement(ZoneList<const AstString*>* labels,
+                                            bool* ok) {
   // WhileStatement ::
   //   'while' '(' Expression ')' Statement
 
@@ -2777,13 +2787,12 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
   ForOfStatement* for_of = stmt->AsForOfStatement();
 
   if (for_of != NULL) {
-    Factory* heap_factory = isolate()->factory();
     Variable* iterable = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_iterable_string());
+        ast_value_factory_->dot_iterable_string());
     Variable* iterator = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_iterator_string());
+        ast_value_factory_->dot_iterator_string());
     Variable* result = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_result_string());
+        ast_value_factory_->dot_result_string());
 
     Expression* assign_iterable;
     Expression* assign_iterator;
@@ -2801,10 +2810,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
     // var iterator = iterable[Symbol.iterator]();
     {
       Expression* iterable_proxy = factory()->NewVariableProxy(iterable);
-      Handle<Symbol> iterator_symbol(
-          isolate()->native_context()->iterator_symbol(), isolate());
-      Expression* iterator_symbol_literal = factory()->NewLiteral(
-          iterator_symbol, RelocInfo::kNoPosition);
+      Expression* iterator_symbol_literal =
+          factory()->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
       // FIXME(wingo): Unhappily, it will be a common error that the RHS of a
       // for-of doesn't have a Symbol.iterator property.  We should do better
       // than informing the user that "undefined is not a function".
@@ -2823,8 +2830,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
     // var result = iterator.next();
     {
       Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
-      Expression* next_literal = factory()->NewLiteral(
-          heap_factory->next_string(), RelocInfo::kNoPosition);
+      Expression* next_literal = factory()->NewStringLiteral(
+          ast_value_factory_->next_string(), RelocInfo::kNoPosition);
       Expression* next_property = factory()->NewProperty(
           iterator_proxy, next_literal, RelocInfo::kNoPosition);
       ZoneList<Expression*>* next_arguments =
@@ -2838,8 +2845,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
 
     // result.done
     {
-      Expression* done_literal = factory()->NewLiteral(
-          heap_factory->done_string(), RelocInfo::kNoPosition);
+      Expression* done_literal = factory()->NewStringLiteral(
+          ast_value_factory_->done_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       result_done = factory()->NewProperty(
           result_proxy, done_literal, RelocInfo::kNoPosition);
@@ -2847,8 +2854,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
 
     // each = result.value
     {
-      Expression* value_literal = factory()->NewLiteral(
-          heap_factory->value_string(), RelocInfo::kNoPosition);
+      Expression* value_literal = factory()->NewStringLiteral(
+          ast_value_factory_->value_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       Expression* result_value = factory()->NewProperty(
           result_proxy, value_literal, RelocInfo::kNoPosition);
@@ -2869,9 +2876,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
 
 
 Statement* Parser::DesugarLetBindingsInForStatement(
-    Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
-    Statement* init, Expression* cond, Statement* next, Statement* body,
-    bool* ok) {
+    Scope* inner_scope, ZoneList<const AstString*>* names,
+    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+    Statement* body, bool* ok) {
   // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
   // copied into a new environment. After copying, the "next" statement of the
   // loop is executed to update the loop variables. The loop condition is
@@ -2912,10 +2919,7 @@ Statement* Parser::DesugarLetBindingsInForStatement(
                                            RelocInfo::kNoPosition);
   outer_block->AddStatement(init, zone());
 
-  Handle<String> temp_name = isolate()->factory()->dot_for_string();
-  Handle<Smi> smi0 = handle(Smi::FromInt(0), isolate());
-  Handle<Smi> smi1 = handle(Smi::FromInt(1), isolate());
-
+  const AstString* temp_name = ast_value_factory_->dot_for_string();
 
   // For each let variable x:
   //   make statement: temp_x = x.
@@ -2936,7 +2940,7 @@ Statement* Parser::DesugarLetBindingsInForStatement(
   // Make statement: flag = 1.
   {
     VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
-    Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
     Assignment* assignment = factory()->NewAssignment(
         Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
     Statement* assignment_statement = factory()->NewExpressionStatement(
@@ -2976,7 +2980,7 @@ Statement* Parser::DesugarLetBindingsInForStatement(
     Expression* compare = NULL;
     // Make compare expresion: flag == 1.
     {
-      Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
       VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
       compare = factory()->NewCompareOperation(
           Token::EQ, flag_proxy, const1, pos);
@@ -2985,7 +2989,7 @@ Statement* Parser::DesugarLetBindingsInForStatement(
     // Make statement: flag = 0.
     {
       VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
-      Expression* const0 = factory()->NewLiteral(smi0, RelocInfo::kNoPosition);
+      Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
       Assignment* assignment = factory()->NewAssignment(
           Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
       clear_flag = factory()->NewExpressionStatement(assignment, pos);
@@ -2999,7 +3003,7 @@ Statement* Parser::DesugarLetBindingsInForStatement(
   // Make statement: if (cond) { } else { break; }.
   {
     Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
-    BreakableStatement* t = LookupBreakTarget(Handle<String>(), CHECK_OK);
+    BreakableStatement* t = LookupBreakTarget(NULL, CHECK_OK);
     Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition);
     Statement* if_not_cond_break = factory()->NewIfStatement(
         cond, empty, stop, cond->position());
@@ -3030,13 +3034,14 @@ Statement* Parser::DesugarLetBindingsInForStatement(
 }
 
 
-Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseForStatement(ZoneList<const AstString*>* labels,
+                                     bool* ok) {
   // ForStatement ::
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
 
   int pos = peek_position();
   Statement* init = NULL;
-  ZoneStringList let_bindings(1, zone());
+  ZoneList<const AstString*> let_bindings(1, zone());
 
   // Create an in-between scope for let-bound iteration variables.
   Scope* saved_scope = scope_;
@@ -3049,7 +3054,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
   if (peek() != Token::SEMICOLON) {
     if (peek() == Token::VAR || peek() == Token::CONST) {
       bool is_const = peek() == Token::CONST;
-      Handle<String> name;
+      const AstString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
           ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
@@ -3057,7 +3062,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
       bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
-      if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
+      if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
         Interface* interface =
             is_const ? Interface::NewConst() : Interface::NewValue();
         ForEachStatement* loop =
@@ -3085,12 +3090,12 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
         init = variable_statement;
       }
     } else if (peek() == Token::LET) {
-      Handle<String> name;
+      const AstString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
-         ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
-                                   &name, CHECK_OK);
-      bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+          ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
+                                    &name, CHECK_OK);
+      bool accept_IN = name != NULL && decl_props != kHasInitializers;
       bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
@@ -3110,14 +3115,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
 
         // TODO(keuchel): Move the temporary variable to the block scope, after
         // implementing stack allocated block scoped variables.
-        Factory* heap_factory = isolate()->factory();
-        Handle<String> tempstr;
-        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-            isolate(), tempstr,
-            heap_factory->NewConsString(heap_factory->dot_for_string(), name),
-            0);
-        Handle<String> tempname = heap_factory->InternalizeString(tempstr);
-        Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
+        Variable* temp = scope_->DeclarationScope()->NewTemporary(
+            ast_value_factory_->dot_for_string());
         VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
         ForEachStatement* loop =
             factory()->NewForEachStatement(mode, labels, pos);
@@ -3248,7 +3247,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
 }
 
 
-void Parser::ReportInvalidCachedData(Handle<String> name, bool* ok) {
+void Parser::ReportInvalidCachedData(const AstString* name, bool* ok) {
   ParserTraits::ReportMessage("invalid_cached_data_function", name);
   *ok = false;
 }
@@ -3298,7 +3297,7 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
 
 
 FunctionLiteral* Parser::ParseFunctionLiteral(
-    Handle<String> function_name,
+    const AstString* function_name,
     Scanner::Location function_name_location,
     bool name_is_strict_reserved,
     bool is_generator,
@@ -3314,11 +3313,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   // Anonymous functions were passed either the empty symbol or a null
   // handle as the function name.  Remember if we were passed a non-empty
   // handle to decide whether to invoke function name inference.
-  bool should_infer_name = function_name.is_null();
+  bool should_infer_name = function_name == NULL;
 
   // We want a non-null handle as the function name.
   if (should_infer_name) {
-    function_name = isolate()->factory()->empty_string();
+    function_name = ast_value_factory_->empty_string();
   }
 
   int num_parameters = 0;
@@ -3370,7 +3369,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   AstProperties ast_properties;
   BailoutReason dont_optimize_reason = kNoReason;
   // Parse function body.
-  { FunctionState function_state(&function_state_, &scope_, scope, zone());
+  {
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
     scope_->SetScopeName(function_name);
 
     if (is_generator) {
@@ -3383,7 +3384,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
       // in a temporary variable, a definition that is used by "yield"
       // expressions. This also marks the FunctionState as a generator.
       Variable* temp = scope_->DeclarationScope()->NewTemporary(
-          isolate()->factory()->dot_generator_object_string());
+          ast_value_factory_->dot_generator_object_string());
       function_state.set_generator_object_variable(temp);
     }
 
@@ -3402,7 +3403,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
     bool done = (peek() == Token::RPAREN);
     while (!done) {
       bool is_strict_reserved = false;
-      Handle<String> param_name =
+      const AstString* param_name =
           ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
 
       // Store locations for possible future error reports.
@@ -3446,6 +3447,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
       VariableMode fvar_mode =
           allow_harmony_scoping() && strict_mode() == STRICT ? CONST
                                                              : CONST_LEGACY;
+      ASSERT(function_name != NULL);
       fvar = new(zone()) Variable(scope_,
          function_name, fvar_mode, true /* is valid LHS */,
          Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
@@ -3549,6 +3551,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
       : FunctionLiteral::kNotGenerator;
   FunctionLiteral* function_literal =
       factory()->NewFunctionLiteral(function_name,
+                                    ast_value_factory_,
                                     scope,
                                     body,
                                     materialized_literal_count,
@@ -3570,7 +3573,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
 }
 
 
-void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+void Parser::SkipLazyFunctionBody(const AstString* function_name,
                                   int* materialized_literal_count,
                                   int* expected_property_count,
                                   bool* ok) {
@@ -3649,7 +3652,7 @@ void Parser::SkipLazyFunctionBody(Handle<String> function_name,
 
 
 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
-    Handle<String> function_name, int pos, Variable* fvar,
+    const AstString* function_name, int pos, Variable* fvar,
     Token::Value fvar_init_op, bool is_generator, bool* ok) {
   // Everything inside an eagerly parsed function will be parsed eagerly
   // (see comment above).
@@ -3672,7 +3675,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
     ZoneList<Expression*>* arguments =
         new(zone()) ZoneList<Expression*>(0, zone());
     CallRuntime* allocation = factory()->NewCallRuntime(
-        isolate()->factory()->empty_string(),
+        ast_value_factory_->empty_string(),
         Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
         arguments, pos);
     VariableProxy* init_proxy = factory()->NewVariableProxy(
@@ -3692,10 +3695,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
   if (is_generator) {
     VariableProxy* get_proxy = factory()->NewVariableProxy(
         function_state_->generator_object_variable());
-    Expression *undefined = factory()->NewLiteral(
-        isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
-    Yield* yield = factory()->NewYield(
-        get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
+    Expression* undefined =
+        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+    Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::FINAL,
+                                       RelocInfo::kNoPosition);
     body->Add(factory()->NewExpressionStatement(
         yield, RelocInfo::kNoPosition), zone());
   }
@@ -3739,7 +3742,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
   int pos = peek_position();
   Expect(Token::MOD, CHECK_OK);
   // Allow "eval" or "arguments" for backward compatibility.
-  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+  const AstString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
 
   if (extension_ != NULL) {
@@ -3748,7 +3751,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
     scope_->DeclarationScope()->ForceEagerCompilation();
   }
 
-  const Runtime::Function* function = Runtime::FunctionForName(name);
+  const Runtime::Function* function = Runtime::FunctionForName(name->string());
 
   // Check for built-in IS_VAR macro.
   if (function != NULL &&
@@ -3776,7 +3779,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
   }
 
   // Check that the function is defined if it's an inline runtime call.
-  if (function == NULL && name->Get(0) == '_') {
+  if (function == NULL && name->FirstCharacter() == '_') {
     ParserTraits::ReportMessage("not_defined", name);
     *ok = false;
     return NULL;
@@ -3788,8 +3791,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
 
 
 Literal* Parser::GetLiteralUndefined(int position) {
-  return factory()->NewLiteral(
-      isolate()->factory()->undefined_value(), position);
+  return factory()->NewUndefinedLiteral(position);
 }
 
 
@@ -3798,7 +3800,7 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
   if (decl != NULL) {
     // In harmony mode we treat conflicting variable bindinds as early
     // errors. See ES5 16 for a definition of early errors.
-    Handle<String> name = decl->proxy()->name();
+    const AstString* name = decl->proxy()->raw_name();
     int position = decl->proxy()->position();
     Scanner::Location location = position == RelocInfo::kNoPosition
         ? Scanner::Location::invalid()
@@ -3813,7 +3815,7 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
 // Parser support
 
 
-bool Parser::TargetStackContainsLabel(Handle<String> label) {
+bool Parser::TargetStackContainsLabel(const AstString* label) {
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     BreakableStatement* stat = t->node()->AsBreakableStatement();
     if (stat != NULL && ContainsLabel(stat->labels(), label))
@@ -3823,8 +3825,9 @@ bool Parser::TargetStackContainsLabel(Handle<String> label) {
 }
 
 
-BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
-  bool anonymous = label.is_null();
+BreakableStatement* Parser::LookupBreakTarget(const AstString* label,
+                                              bool* ok) {
+  bool anonymous = label == NULL;
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     BreakableStatement* stat = t->node()->AsBreakableStatement();
     if (stat == NULL) continue;
@@ -3838,9 +3841,9 @@ BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
 }
 
 
-IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
+IterationStatement* Parser::LookupContinueTarget(const AstString* label,
                                                  bool* ok) {
-  bool anonymous = label.is_null();
+  bool anonymous = label == NULL;
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     IterationStatement* stat = t->node()->AsIterationStatement();
     if (stat == NULL) continue;
@@ -3873,10 +3876,11 @@ void Parser::ThrowPendingError() {
                              pending_error_location_.end_pos);
     Factory* factory = isolate()->factory();
     bool has_arg =
-        !pending_error_arg_.is_null() || pending_error_char_arg_ != NULL;
+        pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
     Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
-    if (!pending_error_arg_.is_null()) {
-      elements->set(0, *(pending_error_arg_.ToHandleChecked()));
+    if (pending_error_arg_ != NULL) {
+      Handle<String> arg_string = pending_error_arg_->string();
+      elements->set(0, *arg_string);
     } else if (pending_error_char_arg_ != NULL) {
       Handle<String> arg_string =
           factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
@@ -4789,7 +4793,16 @@ bool RegExpParser::ParseRegExp(FlatStringReader* input,
 
 bool Parser::Parse() {
   ASSERT(info()->function() == NULL);
+  ASSERT(info()->ast_value_factory() == NULL);
   FunctionLiteral* result = NULL;
+  ast_value_factory_ = new AstValueFactory(zone());
+  if (allow_natives_syntax() || extension_ != NULL) {
+    // If intrinsics are allowed, the Parser cannot operate independent of the
+    // V8 heap because of Rumtime. Tell the string table to internalize strings
+    // and values right after they're created.
+    ast_value_factory_->Internalize(isolate());
+  }
+
   if (info()->is_lazy()) {
     ASSERT(!info()->is_eval());
     if (info()->shared_info()->is_function()) {
@@ -4815,6 +4828,10 @@ bool Parser::Parse() {
     }
   }
   info()->SetFunction(result);
+  ast_value_factory_->Internalize(isolate());
+  // info takes ownership of ast_value_factory_.
+  info()->SetAstValueFactory(ast_value_factory_);
+  ast_value_factory_ = NULL;
   return (result != NULL);
 }
 
index c7bf8bfd45c0126a87e03bae0f4e3de4cd249098..e3bd0b182984a75137815c8ddec7cf81c60169c6 100644 (file)
@@ -389,7 +389,7 @@ class ParserTraits {
     typedef v8::internal::Zone Zone;
 
     // Return types for traversing functions.
-    typedef Handle<String> Identifier;
+    typedef const AstString* Identifier;
     typedef v8::internal::Expression* Expression;
     typedef Yield* YieldExpression;
     typedef v8::internal::FunctionLiteral* FunctionLiteral;
@@ -421,29 +421,29 @@ class ParserTraits {
   }
 
   // Helper functions for recursive descent.
-  bool IsEvalOrArguments(Handle<String> identifier) const;
+  bool IsEvalOrArguments(const AstString* identifier) const;
 
   // Returns true if the expression is of type "this.foo".
   static bool IsThisProperty(Expression* expression);
 
   static bool IsIdentifier(Expression* expression);
 
-  static Handle<String> AsIdentifier(Expression* expression) {
+  static const AstString* AsIdentifier(Expression* expression) {
     ASSERT(IsIdentifier(expression));
-    return expression->AsVariableProxy()->name();
+    return expression->AsVariableProxy()->raw_name();
   }
 
   static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
     return ObjectLiteral::IsBoilerplateProperty(property);
   }
 
-  static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
-    return !string.is_null() && string->AsArrayIndex(index);
+  static bool IsArrayIndex(const AstString* string, uint32_t* index) {
+    return string->AsArrayIndex(index);
   }
 
   // Functions for encapsulating the differences between parsing and preparsing;
   // operations interleaved with the recursive descent.
-  static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+  static void PushLiteralName(FuncNameInferrer* fni, const AstString* id) {
     fni->PushLiteralName(id);
   }
   void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
@@ -501,16 +501,17 @@ class ParserTraits {
   // type. The first argument may be null (in the handle sense) in
   // which case no arguments are passed to the constructor.
   Expression* NewThrowSyntaxError(
-      const char* type, Handle<Object> arg, int pos);
+      const char* type, const AstString* arg, int pos);
 
   // Generate AST node that throws a TypeError with the given
   // type. Both arguments must be non-null (in the handle sense).
-  Expression* NewThrowTypeError(const char* type, Handle<Object> arg, int pos);
+  Expression* NewThrowTypeError(const char* type, const AstString* arg,
+                                int pos);
 
   // Generic AST generator for throwing errors from compiled code.
   Expression* NewThrowError(
-      Handle<String> constructor, const char* type,
-      Vector<Handle<Object> > arguments, int pos);
+      const AstString* constructor, const char* type,
+      const AstString* arg, int pos);
 
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
@@ -518,16 +519,19 @@ class ParserTraits {
                        const char* arg,
                        bool is_reference_error = false);
   void ReportMessage(const char* message,
-                     MaybeHandle<String> arg,
+                     const char* arg = NULL,
+                     bool is_reference_error = false);
+  void ReportMessage(const char* message,
+                     const AstString* arg,
                      bool is_reference_error = false);
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
-                       MaybeHandle<String> arg,
+                       const AstString* arg,
                        bool is_reference_error = false);
 
   // "null" return type creators.
-  static Handle<String> EmptyIdentifier() {
-    return Handle<String>();
+  static const AstString* EmptyIdentifier() {
+    return NULL;
   }
   static Expression* EmptyExpression() {
     return NULL;
@@ -545,16 +549,16 @@ class ParserTraits {
                              AstNodeFactory<AstConstructionVisitor>* factory);
 
   // Producing data during the recursive descent.
-  Handle<String> GetSymbol(Scanner* scanner = NULL);
-  Handle<String> NextLiteralString(Scanner* scanner,
-                                   PretenureFlag tenured);
+  const AstString* GetSymbol(Scanner* scanner);
+  const AstString* GetNextSymbol(Scanner* scanner);
+
   Expression* ThisExpression(Scope* scope,
                              AstNodeFactory<AstConstructionVisitor>* factory);
   Literal* ExpressionFromLiteral(
       Token::Value token, int pos, Scanner* scanner,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromIdentifier(
-      Handle<String> name, int pos, Scope* scope,
+      const AstString* name, int pos, Scope* scope,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromString(
       int pos, Scanner* scanner,
@@ -572,7 +576,7 @@ class ParserTraits {
   // Temporary glue; these functions will move to ParserBase.
   Expression* ParseV8Intrinsic(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
-      Handle<String> name,
+      const AstString* name,
       Scanner::Location function_name_location,
       bool name_is_strict_reserved,
       bool is_generator,
@@ -643,7 +647,7 @@ class Parser : public ParserBase<ParserTraits> {
                                   Handle<String> source);
 
   // Report syntax error
-  void ReportInvalidCachedData(Handle<String> name, bool* ok);
+  void ReportInvalidCachedData(const AstString* name, bool* ok);
 
   void SetCachedData(ScriptData** data,
                      CachedDataMode cached_data_mode) {
@@ -670,8 +674,9 @@ class Parser : public ParserBase<ParserTraits> {
   // for failure at the call sites.
   void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
                             bool is_eval, bool is_global, bool* ok);
-  Statement* ParseModuleElement(ZoneStringList* labels, bool* ok);
-  Statement* ParseModuleDeclaration(ZoneStringList* names, bool* ok);
+  Statement* ParseModuleElement(ZoneList<const AstString*>* labels, bool* ok);
+  Statement* ParseModuleDeclaration(ZoneList<const AstString*>* names,
+                                    bool* ok);
   Module* ParseModule(bool* ok);
   Module* ParseModuleLiteral(bool* ok);
   Module* ParseModulePath(bool* ok);
@@ -680,38 +685,42 @@ class Parser : public ParserBase<ParserTraits> {
   Module* ParseModuleSpecifier(bool* ok);
   Block* ParseImportDeclaration(bool* ok);
   Statement* ParseExportDeclaration(bool* ok);
-  Statement* ParseBlockElement(ZoneStringList* labels, bool* ok);
-  Statement* ParseStatement(ZoneStringList* labels, bool* ok);
-  Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok);
+  Statement* ParseBlockElement(ZoneList<const AstString*>* labels, bool* ok);
+  Statement* ParseStatement(ZoneList<const AstString*>* labels, bool* ok);
+  Statement* ParseFunctionDeclaration(ZoneList<const AstString*>* names,
+                                      bool* ok);
   Statement* ParseNativeDeclaration(bool* ok);
-  Block* ParseBlock(ZoneStringList* labels, bool* ok);
+  Block* ParseBlock(ZoneList<const AstString*>* labels, bool* ok);
   Block* ParseVariableStatement(VariableDeclarationContext var_context,
-                                ZoneStringList* names,
+                                ZoneList<const AstString*>* names,
                                 bool* ok);
   Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
                                    VariableDeclarationProperties* decl_props,
-                                   ZoneStringList* names,
-                                   Handle<String>* out,
+                                   ZoneList<const AstString*>* names,
+                                   const AstString** out,
                                    bool* ok);
-  Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
-                                                bool* ok);
-  IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseExpressionOrLabelledStatement(
+      ZoneList<const AstString*>* labels, bool* ok);
+  IfStatement* ParseIfStatement(ZoneList<const AstString*>* labels, bool* ok);
   Statement* ParseContinueStatement(bool* ok);
-  Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseBreakStatement(ZoneList<const AstString*>* labels, bool* ok);
   Statement* ParseReturnStatement(bool* ok);
-  Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseWithStatement(ZoneList<const AstString*>* labels, bool* ok);
   CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
-  SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
-  DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
-  WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
-  Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+  SwitchStatement* ParseSwitchStatement(ZoneList<const AstString*>* labels,
+                                        bool* ok);
+  DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstString*>* labels,
+                                          bool* ok);
+  WhileStatement* ParseWhileStatement(ZoneList<const AstString*>* labels,
+                                      bool* ok);
+  Statement* ParseForStatement(ZoneList<const AstString*>* labels, bool* ok);
   Statement* ParseThrowStatement(bool* ok);
   Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
   TryStatement* ParseTryStatement(bool* ok);
   DebuggerStatement* ParseDebuggerStatement(bool* ok);
 
   // Support for hamony block scoped bindings.
-  Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
+  Block* ParseScopedBlock(ZoneList<const AstString*>* labels, bool* ok);
 
   // Initialize the components of a for-in / for-of statement.
   void InitializeForEachStatement(ForEachStatement* stmt,
@@ -719,12 +728,12 @@ class Parser : public ParserBase<ParserTraits> {
                                   Expression* subject,
                                   Statement* body);
   Statement* DesugarLetBindingsInForStatement(
-      Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
-      Statement* init, Expression* cond, Statement* next, Statement* body,
-      bool* ok);
+      Scope* inner_scope, ZoneList<const AstString*>* names,
+      ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+      Statement* body, bool* ok);
 
   FunctionLiteral* ParseFunctionLiteral(
-      Handle<String> name,
+      const AstString* name,
       Scanner::Location function_name_location,
       bool name_is_strict_reserved,
       bool is_generator,
@@ -752,14 +761,14 @@ class Parser : public ParserBase<ParserTraits> {
   void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
 
   // Parser support
-  VariableProxy* NewUnresolved(Handle<String> name,
+  VariableProxy* NewUnresolved(const AstString* name,
                                VariableMode mode,
                                Interface* interface);
   void Declare(Declaration* declaration, bool resolve, bool* ok);
 
-  bool TargetStackContainsLabel(Handle<String> label);
-  BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
-  IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+  bool TargetStackContainsLabel(const AstString* label);
+  BreakableStatement* LookupBreakTarget(const AstString* label, bool* ok);
+  IterationStatement* LookupContinueTarget(const AstString* label, bool* ok);
 
   void RegisterTargetUse(Label* target, Target* stop);
 
@@ -769,7 +778,7 @@ class Parser : public ParserBase<ParserTraits> {
 
   // Skip over a lazy function, either using cached data if we have it, or
   // by parsing the function with PreParser. Consumes the ending }.
-  void SkipLazyFunctionBody(Handle<String> function_name,
+  void SkipLazyFunctionBody(const AstString* function_name,
                             int* materialized_literal_count,
                             int* expected_property_count,
                             bool* ok);
@@ -778,7 +787,7 @@ class Parser : public ParserBase<ParserTraits> {
       SingletonLogger* logger);
 
   // Consumes the ending }.
-  ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name,
+  ZoneList<Statement*>* ParseEagerFunctionBody(const AstString* function_name,
                                                int pos,
                                                Variable* fvar,
                                                Token::Value fvar_init_op,
@@ -796,6 +805,7 @@ class Parser : public ParserBase<ParserTraits> {
   Target* target_stack_;  // for break, continue statements
   ScriptData** cached_data_;
   CachedDataMode cached_data_mode_;
+  AstValueFactory* ast_value_factory_;
 
   CompilationInfo* info_;
 
@@ -803,7 +813,7 @@ class Parser : public ParserBase<ParserTraits> {
   bool has_pending_error_;
   Scanner::Location pending_error_location_;
   const char* pending_error_message_;
-  MaybeHandle<String> pending_error_arg_;
+  const AstString* pending_error_arg_;
   const char* pending_error_char_arg_;
   bool pending_error_is_reference_error_;
 };
index 828f284c1648717b073bf125a54cb64a65ab6293..287c26bf742ecd2ab89fd80945317e6b13f1d592 100644 (file)
@@ -149,7 +149,8 @@ class ParserBase : public Traits {
         FunctionState** function_state_stack,
         typename Traits::Type::Scope** scope_stack,
         typename Traits::Type::Scope* scope,
-        typename Traits::Type::Zone* zone = NULL);
+        typename Traits::Type::Zone* zone = NULL,
+        AstValueFactory* ast_value_factory = NULL);
     ~FunctionState();
 
     int NextMaterializedLiteralIndex() {
@@ -356,7 +357,9 @@ class ParserBase : public Traits {
 
   void ReportMessageAt(Scanner::Location location, const char* message,
                        bool is_reference_error = false) {
-    Traits::ReportMessageAt(location, message, NULL, is_reference_error);
+    Traits::ReportMessageAt(location, message,
+                            reinterpret_cast<const char*>(NULL),
+                            is_reference_error);
   }
 
   void ReportUnexpectedToken(Token::Value token);
@@ -743,9 +746,9 @@ class PreParserScope {
 
 class PreParserFactory {
  public:
-  explicit PreParserFactory(void* extra_param) {}
-  PreParserExpression NewLiteral(PreParserIdentifier identifier,
-                                 int pos) {
+  explicit PreParserFactory(void* extra_param1, void* extra_param2) {}
+  PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
+                                       int pos) {
     return PreParserExpression::Default();
   }
   PreParserExpression NewNumberLiteral(double number,
@@ -997,8 +1000,8 @@ class PreParserTraits {
 
   // Producing data during the recursive descent.
   PreParserIdentifier GetSymbol(Scanner* scanner);
-  static PreParserIdentifier NextLiteralString(Scanner* scanner,
-                                               PretenureFlag tenured) {
+
+  static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
     return PreParserIdentifier::Default();
   }
 
@@ -1184,7 +1187,8 @@ ParserBase<Traits>::FunctionState::FunctionState(
     FunctionState** function_state_stack,
     typename Traits::Type::Scope** scope_stack,
     typename Traits::Type::Scope* scope,
-    typename Traits::Type::Zone* extra_param)
+    typename Traits::Type::Zone* extra_param,
+    AstValueFactory* ast_value_factory)
     : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
       next_handler_index_(0),
       expected_property_count_(0),
@@ -1196,7 +1200,7 @@ ParserBase<Traits>::FunctionState::FunctionState(
       outer_scope_(*scope_stack),
       saved_ast_node_id_(0),
       extra_param_(extra_param),
-      factory_(extra_param) {
+      factory_(extra_param, ast_value_factory) {
   *scope_stack_ = scope;
   *function_state_stack = this;
   Traits::SetUpFunctionState(this, extra_param);
@@ -1322,14 +1326,14 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
 
   int literal_index = function_state_->NextMaterializedLiteralIndex();
 
-  IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
+  IdentifierT js_pattern = this->GetNextSymbol(scanner());
   if (!scanner()->ScanRegExpFlags()) {
     Next();
     ReportMessage("invalid_regexp_flags");
     *ok = false;
     return Traits::EmptyExpression();
   }
-  IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
+  IdentifierT js_flags = this->GetNextSymbol(scanner());
   Next();
   return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
 }
@@ -1574,7 +1578,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
         }
         // Failed to parse as get/set property, so it's just a normal property
         // (which might be called "get" or "set" or something else).
-        key = factory()->NewLiteral(id, next_pos);
+        key = factory()->NewStringLiteral(id, next_pos);
         break;
       }
       case Token::STRING: {
@@ -1586,7 +1590,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
           key = factory()->NewNumberLiteral(index, next_pos);
           break;
         }
-        key = factory()->NewLiteral(string, next_pos);
+        key = factory()->NewStringLiteral(string, next_pos);
         break;
       }
       case Token::NUMBER: {
@@ -1599,7 +1603,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
         if (Token::IsKeyword(next)) {
           Consume(next);
           IdentifierT string = this->GetSymbol(scanner_);
-          key = factory()->NewLiteral(string, next_pos);
+          key = factory()->NewStringLiteral(string, next_pos);
         } else {
           Token::Value next = Next();
           ReportUnexpectedToken(next);
@@ -1968,7 +1972,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
         int pos = position();
         IdentifierT name = ParseIdentifierName(CHECK_OK);
         result = factory()->NewProperty(
-            result, factory()->NewLiteral(name, pos), pos);
+            result, factory()->NewStringLiteral(name, pos), pos);
         if (fni_ != NULL) this->PushLiteralName(fni_, name);
         break;
       }
@@ -2090,7 +2094,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
         int pos = position();
         IdentifierT name = ParseIdentifierName(CHECK_OK);
         expression = factory()->NewProperty(
-            expression, factory()->NewLiteral(name, pos), pos);
+            expression, factory()->NewStringLiteral(name, pos), pos);
         if (fni_ != NULL) {
           this->PushLiteralName(fni_, name);
         }
index 4edf318fb655bd0dfd7d19235089560346468c7f..1d834ce0722cee51750dc0a51e2d8c63e48784e7 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/v8.h"
 
+#include "src/ast-value-factory.h"
 #include "src/prettyprinter.h"
 #include "src/scopes.h"
 #include "src/platform.h"
@@ -133,7 +134,7 @@ void PrettyPrinter::VisitIfStatement(IfStatement* node) {
 
 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
   Print("continue");
-  ZoneStringList* labels = node->target()->labels();
+  ZoneList<const AstString*>* labels = node->target()->labels();
   if (labels != NULL) {
     Print(" ");
     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
@@ -145,7 +146,7 @@ void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
 
 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
   Print("break");
-  ZoneStringList* labels = node->target()->labels();
+  ZoneList<const AstString*>* labels = node->target()->labels();
   if (labels != NULL) {
     Print(" ");
     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
@@ -524,7 +525,7 @@ void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
 }
 
 
-void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
+void PrettyPrinter::PrintLabels(ZoneList<const AstString*>* labels) {
   if (labels != NULL) {
     for (int i = 0; i < labels->length(); i++) {
       PrintLiteral(labels->at(i), false);
@@ -582,6 +583,11 @@ void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
 }
 
 
+void PrettyPrinter::PrintLiteral(const AstString* value, bool quote) {
+  PrintLiteral(value->string(), quote);
+}
+
+
 void PrettyPrinter::PrintParameters(Scope* scope) {
   Print("(");
   for (int i = 0; i < scope->num_parameters(); i++) {
@@ -676,7 +682,7 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info,
 }
 
 
-void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) {
+void AstPrinter::PrintLabelsIndented(ZoneList<const AstString*>* labels) {
   if (labels == NULL || labels->length() == 0) return;
   PrintIndented("LABELS ");
   PrintLabels(labels);
index 585734ee242c3d7fb2db288b530c443465fb2db6..860ca33c686a1cda919bde997d49ede2c5abe41c 100644 (file)
@@ -44,9 +44,10 @@ class PrettyPrinter: public AstVisitor {
   const char* Output() const { return output_; }
 
   virtual void PrintStatements(ZoneList<Statement*>* statements);
-  void PrintLabels(ZoneStringList* labels);
+  void PrintLabels(ZoneList<const AstString*>* labels);
   virtual void PrintArguments(ZoneList<Expression*>* arguments);
   void PrintLiteral(Handle<Object> value, bool quote);
+  void PrintLiteral(const AstString* value, bool quote);
   void PrintParameters(Scope* scope);
   void PrintDeclarations(ZoneList<Declaration*>* declarations);
   void PrintFunctionLiteral(FunctionLiteral* function);
@@ -83,7 +84,7 @@ class AstPrinter: public PrettyPrinter {
   void PrintLiteralWithModeIndented(const char* info,
                                     Variable* var,
                                     Handle<Object> value);
-  void PrintLabelsIndented(ZoneStringList* labels);
+  void PrintLabelsIndented(ZoneList<const AstString*>* labels);
 
   void inc_indent() { indent_++; }
   void dec_indent() { indent_--; }
index c92ccda730fbe604d04434ab7f7abf6257748eb0..8ec5c5476c45a5de4a16773990c6e79b12b76f3c 100644 (file)
@@ -20,7 +20,9 @@ class Processor: public AstVisitor {
         result_assigned_(false),
         is_set_(false),
         in_try_(false),
-        factory_(zone) {
+        // Passing a null AstValueFactory is fine, because Processor doesn't
+        // need to create strings or literals.
+        factory_(zone, NULL) {
     InitializeAstVisitor(zone);
   }
 
@@ -234,8 +236,10 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
 
   ZoneList<Statement*>* body = function->body();
   if (!body->is_empty()) {
-    Variable* result = scope->NewTemporary(
-        info->isolate()->factory()->dot_result_string());
+    Variable* result =
+        scope->NewTemporary(info->ast_value_factory()->dot_result_string());
+    // The name string must be internalized at this point.
+    ASSERT(!result->name().is_null());
     Processor processor(result, info->zone());
     processor.Process(body);
     if (processor.HasStackOverflow()) return false;
@@ -250,7 +254,7 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
       // coincides with the end of the with scope which is the position of '1'.
       int pos = function->end_position();
       VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
-          result->name(), false, result->interface(), pos);
+          result->raw_name(), false, result->interface(), pos);
       result_proxy->BindTo(result);
       Statement* result_statement =
           processor.factory()->NewReturnStatement(result_proxy, pos);
index 0265a8fa7810a797361e202f05dfd5ff045d11d1..92f0b94053fd78dd8c199a18fb96ea29a9a88645 100644 (file)
@@ -9,6 +9,7 @@
 #include "src/scanner.h"
 
 #include "include/v8stdint.h"
+#include "src/ast-value-factory.h"
 #include "src/char-predicates-inl.h"
 #include "src/conversions-inl.h"
 #include "src/list-inl.h"
@@ -1093,26 +1094,19 @@ bool Scanner::ScanRegExpFlags() {
 }
 
 
-Handle<String> Scanner::AllocateNextLiteralString(Isolate* isolate,
-                                                  PretenureFlag tenured) {
-  if (is_next_literal_one_byte()) {
-    return isolate->factory()->NewStringFromOneByte(
-        next_literal_one_byte_string(), tenured).ToHandleChecked();
-  } else {
-    return isolate->factory()->NewStringFromTwoByte(
-        next_literal_two_byte_string(), tenured).ToHandleChecked();
+const AstString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) {
+  if (is_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(literal_one_byte_string());
   }
+  return ast_value_factory->GetTwoByteString(literal_two_byte_string());
 }
 
 
-Handle<String> Scanner::AllocateInternalizedString(Isolate* isolate) {
-  if (is_literal_one_byte()) {
-    return isolate->factory()->InternalizeOneByteString(
-        literal_one_byte_string());
-  } else {
-    return isolate->factory()->InternalizeTwoByteString(
-        literal_two_byte_string());
+const AstString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) {
+  if (is_next_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
   }
+  return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
 }
 
 
index 2979082e3f152623527df8a69a4b2d177f592323..7d8b2ab4f222a428559b340f0cac1d16c872f714 100644 (file)
@@ -21,6 +21,8 @@ namespace v8 {
 namespace internal {
 
 
+class AstString;
+class AstValueFactory;
 class ParserRecorder;
 
 
@@ -376,9 +378,8 @@ class Scanner {
     return next_.literal_chars->is_contextual_keyword(keyword);
   }
 
-  Handle<String> AllocateNextLiteralString(Isolate* isolate,
-                                           PretenureFlag tenured);
-  Handle<String> AllocateInternalizedString(Isolate* isolate);
+  const AstString* CurrentSymbol(AstValueFactory* ast_value_factory);
+  const AstString* NextSymbol(AstValueFactory* ast_value_factory);
 
   double DoubleValue();
   bool UnescapedLiteralMatches(const char* data, int length) {
index d84c5bf0057b16779cfda42d2da65bcc23f745b4..bce8244ca7bb64ca97c566dae28404b56bf7ed22 100644 (file)
@@ -540,7 +540,7 @@ Handle<ModuleInfo> ModuleInfo::Create(
   for (Interface::Iterator it = interface->iterator();
        !it.done(); it.Advance(), ++i) {
     Variable* var = scope->LookupLocal(it.name());
-    info->set_name(i, *it.name());
+    info->set_name(i, *(it.name()->string()));
     info->set_mode(i, var->mode());
     ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
     if (var->mode() == MODULE) {
index 497f7940adfb3e42963ba21eb0f58b70adae6b5a..31347415292810354dec1d8c9553a5ef62870484 100644 (file)
@@ -24,34 +24,28 @@ namespace internal {
 //       use. Because a Variable holding a handle with the same location exists
 //       this is ensured.
 
-static bool Match(void* key1, void* key2) {
-  String* name1 = *reinterpret_cast<String**>(key1);
-  String* name2 = *reinterpret_cast<String**>(key2);
-  ASSERT(name1->IsInternalizedString());
-  ASSERT(name2->IsInternalizedString());
-  return name1 == name2;
-}
-
-
 VariableMap::VariableMap(Zone* zone)
-    : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
+    : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
       zone_(zone) {}
 VariableMap::~VariableMap() {}
 
 
 Variable* VariableMap::Declare(
     Scope* scope,
-    Handle<String> name,
+    const AstString* name,
     VariableMode mode,
     bool is_valid_lhs,
     Variable::Kind kind,
     InitializationFlag initialization_flag,
     Interface* interface) {
-  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
-                                 ZoneAllocationPolicy(zone()));
+  // AstStrings are unambiguous, i.e., the same string is always represented by
+  // the same AstString*.
+  // FIXME(marja): fix the type of Lookup.
+  Entry* p = ZoneHashMap::Lookup(const_cast<AstString*>(name), name->hash(),
+                                 true, ZoneAllocationPolicy(zone()));
   if (p->value == NULL) {
     // The variable has not been declared yet -> insert it.
-    ASSERT(p->key == name.location());
+    ASSERT(p->key == name);
     p->value = new(zone()) Variable(scope,
                                     name,
                                     mode,
@@ -64,11 +58,11 @@ Variable* VariableMap::Declare(
 }
 
 
-Variable* VariableMap::Lookup(Handle<String> name) {
-  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
-                                 ZoneAllocationPolicy(NULL));
+Variable* VariableMap::Lookup(const AstString* name) {
+  Entry* p = ZoneHashMap::Lookup(const_cast<AstString*>(name), name->hash(),
+                                 false, ZoneAllocationPolicy(NULL));
   if (p != NULL) {
-    ASSERT(*reinterpret_cast<String**>(p->key) == *name);
+    ASSERT(reinterpret_cast<const AstString*>(p->key) == name);
     ASSERT(p->value != NULL);
     return reinterpret_cast<Variable*>(p->value);
   }
@@ -79,7 +73,8 @@ Variable* VariableMap::Lookup(Handle<String> name) {
 // ----------------------------------------------------------------------------
 // Implementation of Scope
 
-Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
+Scope::Scope(Scope* outer_scope, ScopeType scope_type,
+             AstValueFactory* ast_value_factory, Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(4, zone),
       variables_(zone),
@@ -92,6 +87,7 @@ Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
                  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
                      ? Interface::NewModule(zone) : NULL),
       already_resolved_(false),
+      ast_value_factory_(ast_value_factory),
       zone_(zone) {
   SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
   // The outermost scope must be a global scope.
@@ -103,6 +99,7 @@ Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
 Scope::Scope(Scope* inner_scope,
              ScopeType scope_type,
              Handle<ScopeInfo> scope_info,
+             AstValueFactory* value_factory,
              Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(4, zone),
@@ -114,6 +111,7 @@ Scope::Scope(Scope* inner_scope,
       decls_(4, zone),
       interface_(NULL),
       already_resolved_(true),
+      ast_value_factory_(value_factory),
       zone_(zone) {
   SetDefaults(scope_type, NULL, scope_info);
   if (!scope_info.is_null()) {
@@ -126,7 +124,8 @@ Scope::Scope(Scope* inner_scope,
 }
 
 
-Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
+Scope::Scope(Scope* inner_scope, const AstString* catch_variable_name,
+             AstValueFactory* value_factory, Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(1, zone),
       variables_(zone),
@@ -137,6 +136,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
       decls_(0, zone),
       interface_(NULL),
       already_resolved_(true),
+      ast_value_factory_(value_factory),
       zone_(zone) {
   SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
   AddInnerScope(inner_scope);
@@ -157,7 +157,7 @@ void Scope::SetDefaults(ScopeType scope_type,
                         Handle<ScopeInfo> scope_info) {
   outer_scope_ = outer_scope;
   scope_type_ = scope_type;
-  scope_name_ = isolate_->factory()->empty_string();
+  scope_name_ = ast_value_factory_->empty_string();
   dynamics_ = NULL;
   receiver_ = NULL;
   function_ = NULL;
@@ -199,6 +199,7 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
       Scope* with_scope = new(zone) Scope(current_scope,
                                           WITH_SCOPE,
                                           Handle<ScopeInfo>::null(),
+                                          global_scope->ast_value_factory_,
                                           zone);
       current_scope = with_scope;
       // All the inner scopes are inside a with.
@@ -211,30 +212,36 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
       current_scope = new(zone) Scope(current_scope,
                                       GLOBAL_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsModuleContext()) {
       ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
       current_scope = new(zone) Scope(current_scope,
                                       MODULE_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsFunctionContext()) {
       ScopeInfo* scope_info = context->closure()->shared()->scope_info();
       current_scope = new(zone) Scope(current_scope,
                                       FUNCTION_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsBlockContext()) {
       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
       current_scope = new(zone) Scope(current_scope,
                                       BLOCK_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else {
       ASSERT(context->IsCatchContext());
       String* name = String::cast(context->extension());
-      current_scope = new(zone) Scope(
-          current_scope, Handle<String>(name), zone);
+      current_scope = new (zone) Scope(
+          current_scope,
+          global_scope->ast_value_factory_->GetString(Handle<String>(name)),
+          global_scope->ast_value_factory_, zone);
     }
     if (contains_with) current_scope->RecordWithStatement();
     if (innermost_scope == NULL) innermost_scope = current_scope;
@@ -266,7 +273,9 @@ bool Scope::Analyze(CompilationInfo* info) {
 
   // Allocate the variables.
   {
-    AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
+    // Passing NULL as AstValueFactory is ok, because AllocateVariables doesn't
+    // need to create new strings or values.
+    AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone(), NULL);
     if (!top->AllocateVariables(info, &ast_node_factory)) return false;
   }
 
@@ -310,7 +319,7 @@ void Scope::Initialize() {
   if (is_declaration_scope()) {
     Variable* var =
         variables_.Declare(this,
-                           isolate_->factory()->this_string(),
+                           ast_value_factory_->this_string(),
                            VAR,
                            false,
                            Variable::THIS,
@@ -327,7 +336,7 @@ void Scope::Initialize() {
     // Note that it might never be accessed, in which case it won't be
     // allocated during variable allocation.
     variables_.Declare(this,
-                       isolate_->factory()->arguments_string(),
+                       ast_value_factory_->arguments_string(),
                        VAR,
                        true,
                        Variable::ARGUMENTS,
@@ -366,23 +375,28 @@ Scope* Scope::FinalizeBlockScope() {
 }
 
 
-Variable* Scope::LookupLocal(Handle<String> name) {
+Variable* Scope::LookupLocal(const AstString* name) {
   Variable* result = variables_.Lookup(name);
   if (result != NULL || scope_info_.is_null()) {
     return result;
   }
+  // The Scope is backed up by ScopeInfo. This means it cannot operate in a
+  // heap-independent mode, and all strings must be internalized immediately. So
+  // it's ok to get the Handle<String> here.
+  Handle<String> name_handle = name->string();
   // If we have a serialized scope info, we might find the variable there.
   // There should be no local slot with the given name.
-  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
+  ASSERT(scope_info_->StackSlotIndex(*name_handle) < 0);
 
   // Check context slot lookup.
   VariableMode mode;
   Variable::Location location = Variable::CONTEXT;
   InitializationFlag init_flag;
-  int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag);
+  int index =
+      ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &init_flag);
   if (index < 0) {
     // Check parameters.
-    index = scope_info_->ParameterIndex(*name);
+    index = scope_info_->ParameterIndex(*name_handle);
     if (index < 0) return NULL;
 
     mode = DYNAMIC;
@@ -397,14 +411,14 @@ Variable* Scope::LookupLocal(Handle<String> name) {
 }
 
 
-Variable* Scope::LookupFunctionVar(Handle<String> name,
+Variable* Scope::LookupFunctionVar(const AstString* name,
                                    AstNodeFactory<AstNullVisitor>* factory) {
-  if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
+  if (function_ != NULL && function_->proxy()->raw_name() == name) {
     return function_->proxy()->var();
   } else if (!scope_info_.is_null()) {
     // If we are backed by a scope info, try to lookup the variable there.
     VariableMode mode;
-    int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
+    int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
     if (index < 0) return NULL;
     Variable* var = new(zone()) Variable(
         this, name, mode, true /* is valid LHS */,
@@ -421,7 +435,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name,
 }
 
 
-Variable* Scope::Lookup(Handle<String> name) {
+Variable* Scope::Lookup(const AstString* name) {
   for (Scope* scope = this;
        scope != NULL;
        scope = scope->outer_scope()) {
@@ -432,7 +446,7 @@ Variable* Scope::Lookup(Handle<String> name) {
 }
 
 
-void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
+void Scope::DeclareParameter(const AstString* name, VariableMode mode) {
   ASSERT(!already_resolved());
   ASSERT(is_function_scope());
   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
@@ -441,7 +455,7 @@ void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
 }
 
 
-Variable* Scope::DeclareLocal(Handle<String> name,
+Variable* Scope::DeclareLocal(const AstString* name,
                               VariableMode mode,
                               InitializationFlag init_flag,
                               Interface* interface) {
@@ -456,7 +470,7 @@ Variable* Scope::DeclareLocal(Handle<String> name,
 }
 
 
-Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
+Variable* Scope::DeclareDynamicGlobal(const AstString* name) {
   ASSERT(is_global_scope());
   return variables_.Declare(this,
                             name,
@@ -479,7 +493,7 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
 }
 
 
-Variable* Scope::NewInternal(Handle<String> name) {
+Variable* Scope::NewInternal(const AstString* name) {
   ASSERT(!already_resolved());
   Variable* var = new(zone()) Variable(this,
                                        name,
@@ -492,7 +506,7 @@ Variable* Scope::NewInternal(Handle<String> name) {
 }
 
 
-Variable* Scope::NewTemporary(Handle<String> name) {
+Variable* Scope::NewTemporary(const AstString* name) {
   ASSERT(!already_resolved());
   Variable* var = new(zone()) Variable(this,
                                        name,
@@ -530,7 +544,7 @@ Declaration* Scope::CheckConflictingVarDeclarations() {
   for (int i = 0; i < length; i++) {
     Declaration* decl = decls_[i];
     if (decl->mode() != VAR) continue;
-    Handle<String> name = decl->proxy()->name();
+    const AstString* name = decl->proxy()->raw_name();
 
     // Iterate through all scopes until and including the declaration scope.
     Scope* previous = NULL;
@@ -773,9 +787,8 @@ static void Indent(int n, const char* str) {
 }
 
 
-static void PrintName(Handle<String> name) {
-  SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
-  PrintF("%s", s.get());
+static void PrintName(const AstString* name) {
+  PrintF("%.*s", name->length(), name->raw_data());
 }
 
 
@@ -803,7 +816,7 @@ static void PrintVar(int indent, Variable* var) {
   if (var->is_used() || !var->IsUnallocated()) {
     Indent(indent, Variable::Mode2String(var->mode()));
     PrintF(" ");
-    PrintName(var->name());
+    PrintName(var->raw_name());
     PrintF(";  // ");
     PrintLocation(var);
     if (var->has_forced_context_allocation()) {
@@ -829,7 +842,7 @@ void Scope::Print(int n) {
 
   // Print header.
   Indent(n0, Header(scope_type_));
-  if (scope_name_->length() > 0) {
+  if (!scope_name_->IsEmpty()) {
     PrintF(" ");
     PrintName(scope_name_);
   }
@@ -839,7 +852,7 @@ void Scope::Print(int n) {
     PrintF(" (");
     for (int i = 0; i < params_.length(); i++) {
       if (i > 0) PrintF(", ");
-      PrintName(params_[i]->name());
+      PrintName(params_[i]->raw_name());
     }
     PrintF(")");
   }
@@ -849,7 +862,7 @@ void Scope::Print(int n) {
   // Function name, if any (named function literals, only).
   if (function_ != NULL) {
     Indent(n1, "// (local) function name: ");
-    PrintName(function_->proxy()->name());
+    PrintName(function_->proxy()->raw_name());
     PrintF("\n");
   }
 
@@ -917,8 +930,8 @@ void Scope::Print(int n) {
 #endif  // DEBUG
 
 
-Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
-  if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
+Variable* Scope::NonLocal(const AstString* name, VariableMode mode) {
+  if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
   VariableMap* map = dynamics_->GetMap(mode);
   Variable* var = map->Lookup(name);
   if (var == NULL) {
@@ -938,7 +951,7 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
 }
 
 
-Variable* Scope::LookupRecursive(Handle<String> name,
+Variable* Scope::LookupRecursive(const AstString* name,
                                  BindingKind* binding_kind,
                                  AstNodeFactory<AstNullVisitor>* factory) {
   ASSERT(binding_kind != NULL);
@@ -1012,7 +1025,7 @@ bool Scope::ResolveVariable(CompilationInfo* info,
 
   // Otherwise, try to resolve the variable.
   BindingKind binding_kind;
-  Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
+  Variable* var = LookupRecursive(proxy->raw_name(), &binding_kind, factory);
   switch (binding_kind) {
     case BOUND:
       // We found a variable binding.
@@ -1024,29 +1037,29 @@ bool Scope::ResolveVariable(CompilationInfo* info,
       // scope which was not promoted to a context, this can happen if we use
       // debugger to evaluate arbitrary expressions at a break point).
       if (var->IsGlobalObjectProperty()) {
-        var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+        var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
       } else if (var->is_dynamic()) {
-        var = NonLocal(proxy->name(), DYNAMIC);
+        var = NonLocal(proxy->raw_name(), DYNAMIC);
       } else {
         Variable* invalidated = var;
-        var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
+        var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
         var->set_local_if_not_shadowed(invalidated);
       }
       break;
 
     case UNBOUND:
       // No binding has been found. Declare a variable on the global object.
-      var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
+      var = info->global_scope()->DeclareDynamicGlobal(proxy->raw_name());
       break;
 
     case UNBOUND_EVAL_SHADOWED:
       // No binding has been found. But some scope makes a sloppy 'eval' call.
-      var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+      var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
       break;
 
     case DYNAMIC_LOOKUP:
       // The variable could not be resolved statically.
-      var = NonLocal(proxy->name(), DYNAMIC);
+      var = NonLocal(proxy->raw_name(), DYNAMIC);
       break;
   }
 
@@ -1069,8 +1082,10 @@ bool Scope::ResolveVariable(CompilationInfo* info,
   if (FLAG_harmony_modules) {
     bool ok;
 #ifdef DEBUG
-    if (FLAG_print_interface_details)
-      PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
+    if (FLAG_print_interface_details) {
+      PrintF("# Resolve %.*s:\n", var->raw_name()->length(),
+             var->raw_name()->raw_data());
+    }
 #endif
     proxy->interface()->Unify(var->interface(), zone(), &ok);
     if (!ok) {
@@ -1150,7 +1165,7 @@ bool Scope::MustAllocate(Variable* var) {
   // Give var a read/write use if there is a chance it might be accessed
   // via an eval() call.  This is only possible if the variable has a
   // visible name.
-  if ((var->is_this() || var->name()->length() > 0) &&
+  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
       (var->has_forced_context_allocation() ||
        scope_calls_eval_ ||
        inner_scope_calls_eval_ ||
@@ -1211,7 +1226,7 @@ void Scope::AllocateHeapSlot(Variable* var) {
 
 void Scope::AllocateParameterLocals() {
   ASSERT(is_function_scope());
-  Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
+  Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
 
   bool uses_sloppy_arguments = false;
@@ -1352,10 +1367,9 @@ void Scope::AllocateModulesRecursively(Scope* host_scope) {
   if (already_resolved()) return;
   if (is_module_scope()) {
     ASSERT(interface_->IsFrozen());
-    Handle<String> name = isolate_->factory()->InternalizeOneByteString(
-        STATIC_ASCII_VECTOR(".module"));
     ASSERT(module_var_ == NULL);
-    module_var_ = host_scope->NewInternal(name);
+    module_var_ =
+        host_scope->NewInternal(ast_value_factory_->dot_module_string());
     ++host_scope->num_modules_;
   }
 
index 4486921d6a2b0f79097f112b07fe755454306c56..a5c7cdc798f788bccbacd6ee57451f346571d300 100644 (file)
@@ -22,14 +22,14 @@ class VariableMap: public ZoneHashMap {
   virtual ~VariableMap();
 
   Variable* Declare(Scope* scope,
-                    Handle<String> name,
+                    const AstString* name,
                     VariableMode mode,
                     bool is_valid_lhs,
                     Variable::Kind kind,
                     InitializationFlag initialization_flag,
                     Interface* interface = Interface::NewValue());
 
-  Variable* Lookup(Handle<String> name);
+  Variable* Lookup(const AstString* name);
 
   Zone* zone() const { return zone_; }
 
@@ -74,7 +74,8 @@ class Scope: public ZoneObject {
   // ---------------------------------------------------------------------------
   // Construction
 
-  Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone);
+  Scope(Scope* outer_scope, ScopeType scope_type,
+        AstValueFactory* value_factory, Zone* zone);
 
   // Compute top scope and allocate variables. For lazy compilation the top
   // scope only contains the single lazily compiled function, so this
@@ -85,7 +86,7 @@ class Scope: public ZoneObject {
                                       Zone* zone);
 
   // The scope name is only used for printing/debugging.
-  void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
+  void SetScopeName(const AstString* scope_name) { scope_name_ = scope_name; }
 
   void Initialize();
 
@@ -100,18 +101,18 @@ class Scope: public ZoneObject {
   // Declarations
 
   // Lookup a variable in this scope. Returns the variable or NULL if not found.
-  Variable* LookupLocal(Handle<String> name);
+  Variable* LookupLocal(const AstString* name);
 
   // This lookup corresponds to a lookup in the "intermediate" scope sitting
   // between this scope and the outer scope. (ECMA-262, 3rd., requires that
   // the name of named function literal is kept in an intermediate scope
   // in between this scope and the next outer scope.)
-  Variable* LookupFunctionVar(Handle<String> name,
+  Variable* LookupFunctionVar(const AstString* name,
                               AstNodeFactory<AstNullVisitor>* factory);
 
   // Lookup a variable in this scope or outer scopes.
   // Returns the variable or NULL if not found.
-  Variable* Lookup(Handle<String> name);
+  Variable* Lookup(const AstString* name);
 
   // Declare the function variable for a function literal. This variable
   // is in an intermediate scope between this function scope and the the
@@ -124,11 +125,11 @@ class Scope: public ZoneObject {
   // Declare a parameter in this scope.  When there are duplicated
   // parameters the rightmost one 'wins'.  However, the implementation
   // expects all parameters to be declared and from left to right.
-  void DeclareParameter(Handle<String> name, VariableMode mode);
+  void DeclareParameter(const AstString* name, VariableMode mode);
 
   // Declare a local variable in this scope. If the variable has been
   // declared before, the previously declared variable is returned.
-  Variable* DeclareLocal(Handle<String> name,
+  Variable* DeclareLocal(const AstString* name,
                          VariableMode mode,
                          InitializationFlag init_flag,
                          Interface* interface = Interface::NewValue());
@@ -137,12 +138,12 @@ class Scope: public ZoneObject {
   // global scope.  The variable was introduced (possibly from an inner
   // scope) by a reference to an unresolved variable with no intervening
   // with statements or eval calls.
-  Variable* DeclareDynamicGlobal(Handle<String> name);
+  Variable* DeclareDynamicGlobal(const AstString* name);
 
   // Create a new unresolved variable.
   template<class Visitor>
   VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
-                               Handle<String> name,
+                               const AstString* name,
                                Interface* interface = Interface::NewValue(),
                                int position = RelocInfo::kNoPosition) {
     // Note that we must not share the unresolved variables with
@@ -167,13 +168,13 @@ class Scope: public ZoneObject {
   // for printing and cannot be used to find the variable.  In particular,
   // the only way to get hold of the temporary is by keeping the Variable*
   // around.
-  Variable* NewInternal(Handle<String> name);
+  Variable* NewInternal(const AstString* name);
 
   // Creates a new temporary variable in this scope.  The name is only used
   // for printing and cannot be used to find the variable.  In particular,
   // the only way to get hold of the temporary is by keeping the Variable*
   // around.  The name should not clash with a legitimate variable names.
-  Variable* NewTemporary(Handle<String> name);
+  Variable* NewTemporary(const AstString* name);
 
   // Adds the specific declaration node to the list of declarations in
   // this scope. The declarations are processed as part of entering
@@ -390,7 +391,7 @@ class Scope: public ZoneObject {
 
   // ---------------------------------------------------------------------------
   // Strict mode support.
-  bool IsDeclared(Handle<String> name) {
+  bool IsDeclared(const AstString* name) {
     // During formal parameter list parsing the scope only contains
     // two variables inserted at initialization: "this" and "arguments".
     // "this" is an invalid parameter name and "arguments" is invalid parameter
@@ -421,7 +422,7 @@ class Scope: public ZoneObject {
   ScopeType scope_type_;
 
   // Debugging support.
-  Handle<String> scope_name_;
+  const AstString* scope_name_;
 
   // The variables declared in this scope:
   //
@@ -497,7 +498,7 @@ class Scope: public ZoneObject {
 
   // Create a non-local variable with a given name.
   // These variables are looked up dynamically at runtime.
-  Variable* NonLocal(Handle<String> name, VariableMode mode);
+  Variable* NonLocal(const AstString* name, VariableMode mode);
 
   // Variable resolution.
   // Possible results of a recursive variable lookup telling if and how a
@@ -548,7 +549,7 @@ class Scope: public ZoneObject {
   // Lookup a variable reference given by name recursively starting with this
   // scope. If the code is executed because of a call to 'eval', the context
   // parameter should be set to the calling context of 'eval'.
-  Variable* LookupRecursive(Handle<String> name,
+  Variable* LookupRecursive(const AstString* name,
                             BindingKind* binding_kind,
                             AstNodeFactory<AstNullVisitor>* factory);
   MUST_USE_RESULT
@@ -592,10 +593,12 @@ class Scope: public ZoneObject {
  private:
   // Construct a scope based on the scope info.
   Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info,
-        Zone* zone);
+        AstValueFactory* value_factory, Zone* zone);
 
   // Construct a catch scope with a binding for the name.
-  Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone);
+  Scope(Scope* inner_scope,
+        const AstString* catch_variable_name,
+        AstValueFactory* value_factory, Zone* zone);
 
   void AddInnerScope(Scope* inner_scope) {
     if (inner_scope != NULL) {
@@ -608,6 +611,7 @@ class Scope: public ZoneObject {
                    Scope* outer_scope,
                    Handle<ScopeInfo> scope_info);
 
+  AstValueFactory* ast_value_factory_;
   Zone* zone_;
 };
 
index b9964dbb51a886b3047cb13b2b76d36354b21f6b..00fcdb53625d4ccc8d31f212f8057e94263513eb 100644 (file)
@@ -375,4 +375,24 @@ void init_memcopy_functions() {
 }
 
 
+bool DoubleToBoolean(double d) {
+  // NaN, +0, and -0 should return the false object
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  union IeeeDoubleLittleEndianArchType u;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  union IeeeDoubleBigEndianArchType u;
+#endif
+  u.d = d;
+  if (u.bits.exp == 2047) {
+    // Detect NaN for IEEE double precision floating point.
+    if ((u.bits.man_low | u.bits.man_high) != 0) return false;
+  }
+  if (u.bits.exp == 0) {
+    // Detect +0, and -0 for IEEE double precision floating point.
+    if ((u.bits.man_low | u.bits.man_high) == 0) return false;
+  }
+  return true;
+}
+
+
 } }  // namespace v8::internal
index a2e3be535d3dc017afdc70a343479c2378bc7771..67b8d79a5f6a586bc1cf1bc4c942798bebc10dcb 100644 (file)
@@ -1572,6 +1572,36 @@ class StringBuilder : public SimpleStringBuilder {
 };
 
 
+bool DoubleToBoolean(double d);
+
+template <typename Stream>
+bool StringToArrayIndex(Stream* stream, uint32_t* index) {
+  uint16_t ch = stream->GetNext();
+
+  // If the string begins with a '0' character, it must only consist
+  // of it to be a legal array index.
+  if (ch == '0') {
+    *index = 0;
+    return !stream->HasMore();
+  }
+
+  // Convert string to uint32 array index; character by character.
+  int d = ch - '0';
+  if (d < 0 || d > 9) return false;
+  uint32_t result = d;
+  while (stream->HasMore()) {
+    d = stream->GetNext() - '0';
+    if (d < 0 || d > 9) return false;
+    // Check that the new result is below the 32 bit limit.
+    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+    result = (result * 10) + d;
+  }
+
+  *index = result;
+  return true;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_UTILS_H_
index 906b6ab7d58cad2d8b7cffe351c4eb41c8d8f655..3fc18fcfc913343053c36a35ab530368eefac5cd 100644 (file)
@@ -33,7 +33,7 @@ const char* Variable::Mode2String(VariableMode mode) {
 
 
 Variable::Variable(Scope* scope,
-                   Handle<String> name,
+                   const AstString* name,
                    VariableMode mode,
                    bool is_valid_ref,
                    Kind kind,
@@ -52,8 +52,6 @@ Variable::Variable(Scope* scope,
     is_used_(false),
     initialization_flag_(initialization_flag),
     interface_(interface) {
-  // Names must be canonicalized for fast equality checks.
-  ASSERT(name->IsInternalizedString());
   // Var declared variables never need initialization.
   ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
 }
index de209d871d56da5b77588b2eaeeec1ae5b484be5..f52a0b95186d136b3d315b3c56b50bc587479dc9 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef V8_VARIABLES_H_
 #define V8_VARIABLES_H_
 
+#include "src/ast-value-factory.h"
 #include "src/zone.h"
 #include "src/interface.h"
 
@@ -52,7 +53,7 @@ class Variable: public ZoneObject {
   };
 
   Variable(Scope* scope,
-           Handle<String> name,
+           const AstString* name,
            VariableMode mode,
            bool is_valid_ref,
            Kind kind,
@@ -70,7 +71,8 @@ class Variable: public ZoneObject {
   // scope is only used to follow the context chain length.
   Scope* scope() const { return scope_; }
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
+  const AstString* raw_name() const { return name_; }
   VariableMode mode() const { return mode_; }
   bool has_forced_context_allocation() const {
     return force_context_allocation_;
@@ -136,7 +138,7 @@ class Variable: public ZoneObject {
 
  private:
   Scope* scope_;
-  Handle<String> name_;
+  const AstString* name_;
   VariableMode mode_;
   Kind kind_;
   Location location_;
index 2285d0cbd427aadf287bac1c281f4fb33a0587d3..a25ae69b6171345733621d12ea43c275e37ea70a 100644 (file)
@@ -41,7 +41,7 @@ TEST(List) {
 
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate);
-  AstNodeFactory<AstNullVisitor> factory(&zone);
+  AstNodeFactory<AstNullVisitor> factory(&zone, NULL);
   AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
   list->Add(node);
   CHECK_EQ(1, list->length());
index 533c6249ca9abee8dd498ffaf216a2c823554744..594ee546690ca1f67b07eb53dd7fa0d03d6778b6 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "src/v8.h"
 
+#include "src/ast-value-factory.h"
 #include "src/compiler.h"
 #include "src/execution.h"
 #include "src/isolate.h"
@@ -796,8 +797,10 @@ void TestScanRegExp(const char* re_source, const char* expected) {
   CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
   CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
   scanner.Next();  // Current token is now the regexp literal.
+  i::AstValueFactory ast_value_factory(NULL);
+  ast_value_factory.Internalize(CcTest::i_isolate());
   i::Handle<i::String> val =
-      scanner.AllocateInternalizedString(CcTest::i_isolate());
+      scanner.CurrentSymbol(&ast_value_factory)->string();
   i::DisallowHeapAllocation no_alloc;
   i::String::FlatContent content = val->GetFlatContent();
   CHECK(content.IsAscii());
index 3890134490c044d5d850de9bca47eba7dcb096c0..bccda67b112dd88af4590986287af6a10d881af7 100644 (file)
         '../../src/assembler.h',
         '../../src/assert-scope.h',
         '../../src/assert-scope.cc',
+        '../../src/ast-value-factory.cc',
+        '../../src/ast-value-factory.h',
         '../../src/ast.cc',
         '../../src/ast.h',
         '../../src/bignum-dtoa.cc',
index c2291857f0ccb30f836a8cf1fa40cae000b5e4dd..f14c0008b42b1fa5794803f534b9acd4c920d8db 100644 (file)
 
 using namespace v8::internal;
 
+class StringResource8 : public v8::String::ExternalAsciiStringResource {
+ public:
+  StringResource8(const char* data, int length)
+      : data_(data), length_(length) { }
+  virtual size_t length() const { return length_; }
+  virtual const char* data() const { return data_; }
+
+ private:
+  const char* data_;
+  int length_;
+};
+
 std::pair<TimeDelta, TimeDelta> RunBaselineParser(
     const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate,
     v8::Handle<v8::Context> context) {
@@ -63,7 +75,9 @@ std::pair<TimeDelta, TimeDelta> RunBaselineParser(
       break;
     }
     case LATIN1: {
-      source_handle = v8::String::NewFromOneByte(isolate, source);
+      StringResource8* string_resource =
+          new StringResource8(reinterpret_cast<const char*>(source), length);
+      source_handle = v8::String::NewExternal(isolate, string_resource);
       break;
     }
   }