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.
--- /dev/null
+// 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
--- /dev/null
+// 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_
// 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),
VariableProxy::VariableProxy(Zone* zone,
- Handle<String> name,
+ const AstString* name,
bool is_this,
Interface* interface,
int position)
is_trivial_(false),
is_lvalue_(false),
interface_(interface) {
- // Names must be canonicalized for fast equality checks.
- ASSERT(name->IsInternalizedString());
}
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
}
-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;
// 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.
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);
}
#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"
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_;
// 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 {
protected:
BreakableStatement(
- Zone* zone, ZoneStringList* labels,
+ Zone* zone, ZoneList<const AstString*>* labels,
BreakableType breakable_type, int position)
: Statement(zone, position),
labels_(labels),
private:
- ZoneStringList* labels_;
+ ZoneList<const AstString*>* labels_;
BreakableType breakable_type_;
Label break_target_;
const BailoutId entry_id_;
protected:
Block(Zone* zone,
- ZoneStringList* labels,
+ ZoneList<const AstString*>* labels,
int capacity,
bool is_initializer_block,
int pos)
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_;
};
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)) {
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)),
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),
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),
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_;
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),
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),
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) { }
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!
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()) { }
private:
Handle<String> ToString();
- Handle<Object> value_;
+ const AstValue* value_;
// TODO(dcarney): remove. this is only needed for Match and Hash.
Isolate* isolate_;
};
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_; }
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),
}
private:
- Handle<String> pattern_;
- Handle<String> flags_;
+ const AstString* pattern_;
+ const AstString* flags_;
};
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_; }
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_;
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; }
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_;
};
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; }
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.
protected:
FunctionLiteral(Zone* zone,
- Handle<String> name,
+ const AstString* name,
+ AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
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),
}
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_;
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_;
};
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_; }
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)
}
VISIT_AND_RETURN(ModuleUrl, module)
}
- Block* NewBlock(ZoneStringList* labels,
+ Block* NewBlock(ZoneList<const AstString*>* labels,
int capacity,
bool is_initializer_block,
int pos) {
}
#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); \
}
#undef STATEMENT_WITH_LABELS
ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
- ZoneStringList* labels,
+ ZoneList<const AstString*>* labels,
int pos) {
switch (visit_mode) {
case ForEachStatement::ENUMERATE: {
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(
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,
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 =
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) {
VISIT_AND_RETURN(CallNew, call)
}
- CallRuntime* NewCallRuntime(Handle<String> name,
+ CallRuntime* NewCallRuntime(const AstString* name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments,
int pos) {
}
FunctionLiteral* NewFunctionLiteral(
- Handle<String> name,
+ const AstString* name,
+ AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
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);
}
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)
private:
Zone* zone_;
Visitor visitor_;
+ AstValueFactory* ast_value_factory_;
};
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);
}
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);
}
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);
}
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;
}
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.
namespace v8 {
namespace internal {
+class AstValueFactory;
class ScriptData;
class HydrogenCodeStub;
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);
int optimization_id_;
+ AstValueFactory* ast_value_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
#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),
}
-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);
}
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.
// 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() {
}
// 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) {
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_;
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") \
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") \
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") \
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_;
#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;
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
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;
#ifndef V8_INTERFACE_H_
#define V8_INTERFACE_H_
+#include "src/ast-value-factory.h"
#include "src/zone-inl.h" // For operator new.
namespace v8 {
// 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
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());
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);
};
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());
}
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);
}
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;
}
// ----------------------------------------------------------------------------
// 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();
}
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());
}
}
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();
}
}
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);
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;
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);
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);
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
}
-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_);
}
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);
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);
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);
}
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
- Handle<String> name,
+ const AstString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
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);
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;
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()) {
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());
if (ok) {
result = factory()->NewFunctionLiteral(
- no_name,
+ ast_value_factory_->empty_string(),
+ ast_value_factory_,
scope_,
body,
function_state.materialized_literal_count(),
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);
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());
: 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(),
// 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
}
-Statement* Parser::ParseModuleElement(ZoneStringList* labels,
+Statement* Parser::ParseModuleElement(ZoneList<const AstString*>* labels,
bool* ok) {
// (Ecma 262 5th Edition, clause 14):
// SourceElement:
!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);
}
}
-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);
#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
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: ");
// 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()),
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...
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);
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();
}
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);
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);
}
-Statement* Parser::ParseBlockElement(ZoneStringList* labels,
+Statement* Parser::ParseBlockElement(ZoneList<const AstString*>* labels,
bool* ok) {
// (Ecma 262 5th Edition, clause 14):
// SourceElement:
}
-Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseStatement(ZoneList<const AstString*>* labels,
+ bool* ok) {
// Statement ::
// Block
// VariableStatement
}
-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.
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;
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) {
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) {
}
-Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseFunctionDeclaration(ZoneList<const AstString*>* names,
+ bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
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(),
}
-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);
}
}
-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 ::
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);
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)?)+[',']
// 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();
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) {
// 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 {
// 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);
}
}
-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;
}
}
}
-Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok) {
+Statement* Parser::ParseExpressionOrLabelledStatement(
+ ZoneList<const AstString*>* labels, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
// 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
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
!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);
}
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);
}
}
-IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
+IfStatement* Parser::ParseIfStatement(ZoneList<const AstString*>* labels,
+ bool* ok) {
// IfStatement ::
// 'if' '(' Expression ')' Statement ('else' Statement)?
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);
}
-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) {
}
// 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);
}
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);
}
-Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseWithStatement(ZoneList<const AstString*>* labels,
+ bool* ok) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
}
-SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
- bool* ok) {
+SwitchStatement* Parser::ParseSwitchStatement(
+ ZoneList<const AstString*>* labels, bool* ok) {
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
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);
}
-DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
- bool* ok) {
+DoWhileStatement* Parser::ParseDoWhileStatement(
+ ZoneList<const AstString*>* labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
}
-WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
+WhileStatement* Parser::ParseWhileStatement(ZoneList<const AstString*>* labels,
+ bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
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;
// 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".
// 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 =
// 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);
// 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);
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
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.
// 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(
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);
// 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);
// 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());
}
-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_;
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,
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 =
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;
// 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);
}
-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;
}
FunctionLiteral* Parser::ParseFunctionLiteral(
- Handle<String> function_name,
+ const AstString* function_name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
// 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;
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) {
// 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);
}
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.
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());
: FunctionLiteral::kNotGenerator;
FunctionLiteral* function_literal =
factory()->NewFunctionLiteral(function_name,
+ ast_value_factory_,
scope,
body,
materialized_literal_count,
}
-void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+void Parser::SkipLazyFunctionBody(const AstString* function_name,
int* materialized_literal_count,
int* expected_property_count,
bool* ok) {
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).
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(
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());
}
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) {
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 &&
}
// 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;
Literal* Parser::GetLiteralUndefined(int position) {
- return factory()->NewLiteral(
- isolate()->factory()->undefined_value(), position);
+ return factory()->NewUndefinedLiteral(position);
}
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()
// 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))
}
-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;
}
-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;
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_))
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()) {
}
}
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);
}
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;
}
// 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);
// 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,
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;
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,
// 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,
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) {
// 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);
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,
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,
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);
// 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);
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,
Target* target_stack_; // for break, continue statements
ScriptData** cached_data_;
CachedDataMode cached_data_mode_;
+ AstValueFactory* ast_value_factory_;
CompilationInfo* info_;
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_;
};
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() {
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);
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,
// 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();
}
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),
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);
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);
}
}
// 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: {
key = factory()->NewNumberLiteral(index, next_pos);
break;
}
- key = factory()->NewLiteral(string, next_pos);
+ key = factory()->NewStringLiteral(string, next_pos);
break;
}
case Token::NUMBER: {
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);
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;
}
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);
}
#include "src/v8.h"
+#include "src/ast-value-factory.h"
#include "src/prettyprinter.h"
#include "src/scopes.h"
#include "src/platform.h"
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
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
}
-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);
}
+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++) {
}
-void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) {
+void AstPrinter::PrintLabelsIndented(ZoneList<const AstString*>* labels) {
if (labels == NULL || labels->length() == 0) return;
PrintIndented("LABELS ");
PrintLabels(labels);
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);
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_--; }
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);
}
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;
// 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);
#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"
}
-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());
}
namespace internal {
+class AstString;
+class AstValueFactory;
class ParserRecorder;
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) {
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) {
// 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,
}
-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);
}
// ----------------------------------------------------------------------------
// 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),
(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.
Scope::Scope(Scope* inner_scope,
ScopeType scope_type,
Handle<ScopeInfo> scope_info,
+ AstValueFactory* value_factory,
Zone* zone)
: isolate_(zone->isolate()),
inner_scopes_(4, zone),
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()) {
}
-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),
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);
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;
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.
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;
// 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;
}
if (is_declaration_scope()) {
Variable* var =
variables_.Declare(this,
- isolate_->factory()->this_string(),
+ ast_value_factory_->this_string(),
VAR,
false,
Variable::THIS,
// 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,
}
-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;
}
-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 */,
}
-Variable* Scope::Lookup(Handle<String> name) {
+Variable* Scope::Lookup(const AstString* name) {
for (Scope* scope = this;
scope != NULL;
scope = scope->outer_scope()) {
}
-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,
}
-Variable* Scope::DeclareLocal(Handle<String> name,
+Variable* Scope::DeclareLocal(const AstString* name,
VariableMode mode,
InitializationFlag init_flag,
Interface* interface) {
}
-Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
+Variable* Scope::DeclareDynamicGlobal(const AstString* name) {
ASSERT(is_global_scope());
return variables_.Declare(this,
name,
}
-Variable* Scope::NewInternal(Handle<String> name) {
+Variable* Scope::NewInternal(const AstString* name) {
ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this,
name,
}
-Variable* Scope::NewTemporary(Handle<String> name) {
+Variable* Scope::NewTemporary(const AstString* name) {
ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this,
name,
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;
}
-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());
}
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()) {
// Print header.
Indent(n0, Header(scope_type_));
- if (scope_name_->length() > 0) {
+ if (!scope_name_->IsEmpty()) {
PrintF(" ");
PrintName(scope_name_);
}
PrintF(" (");
for (int i = 0; i < params_.length(); i++) {
if (i > 0) PrintF(", ");
- PrintName(params_[i]->name());
+ PrintName(params_[i]->raw_name());
}
PrintF(")");
}
// 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");
}
#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) {
}
-Variable* Scope::LookupRecursive(Handle<String> name,
+Variable* Scope::LookupRecursive(const AstString* name,
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL);
// 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.
// 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;
}
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) {
// 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_ ||
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;
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_;
}
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_; }
// ---------------------------------------------------------------------------
// 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
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();
// 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
// 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());
// 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
// 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
// ---------------------------------------------------------------------------
// 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
ScopeType scope_type_;
// Debugging support.
- Handle<String> scope_name_;
+ const AstString* scope_name_;
// The variables declared in this scope:
//
// 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
// 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
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) {
Scope* outer_scope,
Handle<ScopeInfo> scope_info);
+ AstValueFactory* ast_value_factory_;
Zone* zone_;
};
}
+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
};
+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_
Variable::Variable(Scope* scope,
- Handle<String> name,
+ const AstString* name,
VariableMode mode,
bool is_valid_ref,
Kind kind,
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));
}
#ifndef V8_VARIABLES_H_
#define V8_VARIABLES_H_
+#include "src/ast-value-factory.h"
#include "src/zone.h"
#include "src/interface.h"
};
Variable(Scope* scope,
- Handle<String> name,
+ const AstString* name,
VariableMode mode,
bool is_valid_ref,
Kind kind,
// 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_;
private:
Scope* scope_;
- Handle<String> name_;
+ const AstString* name_;
VariableMode mode_;
Kind kind_;
Location location_;
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());
#include "src/v8.h"
+#include "src/ast-value-factory.h"
#include "src/compiler.h"
#include "src/execution.h"
#include "src/isolate.h"
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());
'../../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',
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) {
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;
}
}