New try: Parser: Delay internalizing strings and values

This is a reincarnation of r21841.

The previous try was https://codereview.chromium.org/314603004/ but it regressed
JSBench and morejs.

BUG=
R=rossberg@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21972 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
marja@chromium.org 2014-06-24 14:03:24 +00:00
parent 256d406c73
commit 62ffc7de20
34 changed files with 1579 additions and 630 deletions

View File

@ -447,6 +447,8 @@ source_set("v8_base") {
"src/assembler.h", "src/assembler.h",
"src/assert-scope.h", "src/assert-scope.h",
"src/assert-scope.cc", "src/assert-scope.cc",
"src/ast-value-factory.cc",
"src/ast-value-factory.h",
"src/ast.cc", "src/ast.cc",
"src/ast.h", "src/ast.h",
"src/bignum-dtoa.cc", "src/bignum-dtoa.cc",

View File

@ -5586,7 +5586,7 @@ class Internals {
static const int kNullValueRootIndex = 7; static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8; static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9; 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 // The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory. // to avoid that resource-constrained embedders run low on memory.

409
src/ast-value-factory.cc Normal file
View File

@ -0,0 +1,409 @@
// 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 {
// 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_;
};
}
class AstRawStringInternalizationKey : public HashTableKey {
public:
explicit AstRawStringInternalizationKey(const AstRawString* string)
: string_(string) {}
virtual bool IsMatch(Object* other) V8_OVERRIDE {
if (string_->is_one_byte_)
return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
return String::cast(other)->IsTwoByteEqualTo(
Vector<const uint16_t>::cast(string_->literal_bytes_));
}
virtual uint32_t Hash() V8_OVERRIDE {
return string_->hash() >> Name::kHashShift;
}
virtual uint32_t HashForObject(Object* key) V8_OVERRIDE {
return String::cast(key)->Hash();
}
virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
if (string_->is_one_byte_)
return isolate->factory()->NewOneByteInternalizedString(
string_->literal_bytes_, string_->hash());
return isolate->factory()->NewTwoByteInternalizedString(
Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
}
private:
const AstRawString* string_;
};
void AstRawString::Internalize(Isolate* isolate) {
if (!string_.is_null()) return;
if (literal_bytes_.length() == 0) {
string_ = isolate->factory()->empty_string();
} else {
AstRawStringInternalizationKey key(this);
string_ = StringTable::LookupKey(isolate, &key);
}
}
bool AstRawString::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 AstRawString::IsOneByteEqualTo(const char* data) const {
int length = static_cast<int>(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;
}
bool AstRawString::Compare(void* a, void* b) {
AstRawString* string1 = reinterpret_cast<AstRawString*>(a);
AstRawString* string2 = reinterpret_cast<AstRawString*>(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;
}
void AstConsString::Internalize(Isolate* isolate) {
// AstRawStrings are internalized before AstConsStrings so left and right are
// already internalized.
string_ = isolate->factory()
->NewConsString(left_->string(), right_->string())
.ToHandleChecked();
}
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 AstRawString* 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 AstRawString* AstValueFactory::GetOneByteString(
Vector<const uint8_t> literal) {
uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
literal.start(), literal.length(), hash_seed_);
return GetString(hash, true, literal);
}
const AstRawString* AstValueFactory::GetTwoByteString(
Vector<const uint16_t> literal) {
uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
literal.start(), literal.length(), hash_seed_);
return GetString(hash, false, Vector<const byte>::cast(literal));
}
const AstRawString* 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());
}
const AstConsString* AstValueFactory::NewConsString(
const AstString* left, const AstString* right) {
// This Vector will be valid as long as the Collector is alive (meaning that
// the AstRawString will not be moved).
AstConsString* new_string = new (zone_) AstConsString(left, right);
strings_.Add(new_string);
if (isolate_) {
new_string->Internalize(isolate_);
}
return new_string;
}
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 (int i = 0; i < strings_.length(); ++i) {
strings_[i]->Internalize(isolate);
}
for (int i = 0; i < values_.length(); ++i) {
values_[i]->Internalize(isolate);
}
isolate_ = isolate;
}
const AstValue* AstValueFactory::NewString(const AstRawString* 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 AstRawString*>* 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 AstRawString* AstValueFactory::GetString(
uint32_t 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 AstRawStrings which are in the string_table_. We should not
// return this AstRawString.
AstRawString 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.
int length = literal_bytes.length();
byte* new_literal_bytes = zone_->NewArray<byte>(length);
memcpy(new_literal_bytes, literal_bytes.start(), length);
AstRawString* new_string = new (zone_) AstRawString(
is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
entry->key = new_string;
strings_.Add(new_string);
if (isolate_) {
new_string->Internalize(isolate_);
}
entry->value = reinterpret_cast<void*>(1);
}
return reinterpret_cast<AstRawString*>(entry->key);
}
} } // namespace v8::internal

340
src/ast-value-factory.h Normal file
View File

@ -0,0 +1,340 @@
// 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 ZoneObject {
public:
virtual ~AstString() {}
virtual int length() const = 0;
bool IsEmpty() const { return length() == 0; }
// Puts the string into the V8 heap.
virtual void Internalize(Isolate* isolate) = 0;
// This function can be called after internalizing.
V8_INLINE Handle<String> string() const {
ASSERT(!string_.is_null());
return string_;
}
protected:
// This is null until the string is internalized.
Handle<String> string_;
};
class AstRawString : public AstString {
public:
virtual int length() const V8_OVERRIDE {
if (is_one_byte_)
return literal_bytes_.length();
return literal_bytes_.length() / 2;
}
virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
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();
}
bool is_one_byte() const { return is_one_byte_; }
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;
}
// For storing AstRawStrings in a hash map.
uint32_t hash() const {
return hash_;
}
static bool Compare(void* a, void* b);
private:
friend class AstValueFactory;
friend class AstRawStringInternalizationKey;
AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
uint32_t hash)
: is_one_byte_(is_one_byte), literal_bytes_(literal_bytes), hash_(hash) {}
AstRawString()
: is_one_byte_(true),
hash_(0) {}
bool is_one_byte_;
// Points to memory owned by Zone.
Vector<const byte> literal_bytes_;
uint32_t hash_;
};
class AstConsString : public AstString {
public:
AstConsString(const AstString* left, const AstString* right)
: left_(left),
right_(right) {}
virtual int length() const V8_OVERRIDE {
return left_->length() + right_->length();
}
virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
private:
friend class AstValueFactory;
const AstString* left_;
const AstString* right_;
};
// 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 AstRawString* 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 AstRawString* 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 AstRawString* 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 AstRawString*>* 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 AstRawString* string_;
double number_;
int smi_;
bool bool_;
ZoneList<const AstRawString*>* 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, ".") \
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:
AstValueFactory(Zone* zone, uint32_t hash_seed)
: string_table_(AstRawString::Compare),
zone_(zone),
isolate_(NULL),
hash_seed_(hash_seed) {
#define F(name, str) \
name##_string_ = NULL;
STRING_CONSTANTS(F)
#undef F
}
const AstRawString* GetOneByteString(Vector<const uint8_t> literal);
const AstRawString* GetTwoByteString(Vector<const uint16_t> literal);
const AstRawString* GetString(Handle<String> literal);
const AstConsString* NewConsString(const AstString* left,
const AstString* right);
void Internalize(Isolate* isolate);
bool IsInternalized() {
return isolate_ != NULL;
}
#define F(name, str) \
const AstRawString* name##_string() { \
if (name##_string_ == NULL) { \
const char* data = str; \
name##_string_ = GetOneByteString( \
Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \
static_cast<int>(strlen(data)))); \
} \
return name##_string_; \
}
STRING_CONSTANTS(F)
#undef F
const AstValue* NewString(const AstRawString* 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 AstRawString*>* strings);
const AstValue* NewNull();
const AstValue* NewUndefined();
const AstValue* NewTheHole();
private:
const AstRawString* GetString(uint32_t hash, bool is_one_byte,
Vector<const byte> literal_bytes);
// All strings are copied here, one after another (no NULLs inbetween).
HashMap string_table_;
// For keeping track of all AstValues and AstRawStrings we've created (so that
// they can be internalized later).
List<AstValue*> values_;
List<AstString*> strings_;
Zone* zone_;
Isolate* isolate_;
uint32_t hash_seed_;
#define F(name, str) \
const AstRawString* name##_string_;
STRING_CONSTANTS(F)
#undef F
};
} } // namespace v8::internal
#undef STRING_CONSTANTS
#endif // V8_AST_VALUE_FACTORY_H_

View File

@ -55,14 +55,13 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
// The global identifier "undefined" is immutable. Everything // The global identifier "undefined" is immutable. Everything
// else could be reassigned. // else could be reassigned.
return var != NULL && var->location() == Variable::UNALLOCATED && return var != NULL && var->location() == Variable::UNALLOCATED &&
String::Equals(var_proxy->name(), var_proxy->raw_name()->IsOneByteEqualTo("undefined");
isolate->factory()->undefined_string());
} }
VariableProxy::VariableProxy(Zone* zone, Variable* var, int position) VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
: Expression(zone, position), : Expression(zone, position),
name_(var->name()), name_(var->raw_name()),
var_(NULL), // Will be set by the call to BindTo. var_(NULL), // Will be set by the call to BindTo.
is_this_(var->is_this()), is_this_(var->is_this()),
is_trivial_(false), is_trivial_(false),
@ -73,7 +72,7 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
VariableProxy::VariableProxy(Zone* zone, VariableProxy::VariableProxy(Zone* zone,
Handle<String> name, const AstRawString* name,
bool is_this, bool is_this,
Interface* interface, Interface* interface,
int position) int position)
@ -84,8 +83,6 @@ VariableProxy::VariableProxy(Zone* zone,
is_trivial_(false), is_trivial_(false),
is_lvalue_(false), is_lvalue_(false),
interface_(interface) { interface_(interface) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsInternalizedString());
} }
@ -93,7 +90,7 @@ void VariableProxy::BindTo(Variable* var) {
ASSERT(var_ == NULL); // must be bound only once ASSERT(var_ == NULL); // must be bound only once
ASSERT(var != NULL); // must bind ASSERT(var != NULL); // must bind
ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); 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 // Ideally CONST-ness should match. However, this is very hard to achieve
// because we don't know the exact semantics of conflicting (const and // because we don't know the exact semantics of conflicting (const and
// non-const) multiple variable declarations, const vars introduced via // non-const) multiple variable declarations, const vars introduced via
@ -180,15 +177,13 @@ void FunctionLiteral::InitializeSharedInfo(
} }
ObjectLiteralProperty::ObjectLiteralProperty( ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
Zone* zone, Literal* key, Expression* value) { AstValueFactory* ast_value_factory,
Literal* key, Expression* value) {
emit_store_ = true; emit_store_ = true;
key_ = key; key_ = key;
value_ = value; value_ = value;
Handle<Object> k = key->value(); if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
if (k->IsInternalizedString() &&
String::Equals(Handle<String>::cast(k),
zone->isolate()->factory()->proto_string())) {
kind_ = PROTOTYPE; kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) { } else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL; kind_ = MATERIALIZED_LITERAL;
@ -1122,9 +1117,8 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
// optimize them. // optimize them.
add_flag(kDontInline); add_flag(kDontInline);
} else if (node->function()->intrinsic_type == Runtime::INLINE && } else if (node->function()->intrinsic_type == Runtime::INLINE &&
(node->name()->IsOneByteEqualTo( (node->raw_name()->IsOneByteEqualTo("_ArgumentsLength") ||
STATIC_ASCII_VECTOR("_ArgumentsLength")) || node->raw_name()->IsOneByteEqualTo("_Arguments"))) {
node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
// Don't inline the %_ArgumentsLength or %_Arguments because their // Don't inline the %_ArgumentsLength or %_Arguments because their
// implementation will not work. There is no stack frame to get them // implementation will not work. There is no stack frame to get them
// from. // from.
@ -1139,17 +1133,17 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
Handle<String> Literal::ToString() { Handle<String> Literal::ToString() {
if (value_->IsString()) return Handle<String>::cast(value_); if (value_->IsString()) return value_->AsString()->string();
ASSERT(value_->IsNumber()); ASSERT(value_->IsNumber());
char arr[100]; char arr[100];
Vector<char> buffer(arr, ARRAY_SIZE(arr)); Vector<char> buffer(arr, ARRAY_SIZE(arr));
const char* str; const char* str;
if (value_->IsSmi()) { if (value()->IsSmi()) {
// Optimization only, the heap number case would subsume this. // Optimization only, the heap number case would subsume this.
SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); SNPrintF(buffer, "%d", Smi::cast(*value())->value());
str = arr; str = arr;
} else { } else {
str = DoubleToCString(value_->Number(), buffer); str = DoubleToCString(value()->Number(), buffer);
} }
return isolate_->factory()->NewStringFromAsciiChecked(str); return isolate_->factory()->NewStringFromAsciiChecked(str);
} }

240
src/ast.h
View File

@ -8,6 +8,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/assembler.h" #include "src/assembler.h"
#include "src/ast-value-factory.h"
#include "src/factory.h" #include "src/factory.h"
#include "src/feedback-slots.h" #include "src/feedback-slots.h"
#include "src/interface.h" #include "src/interface.h"
@ -367,11 +368,14 @@ class Expression : public AstNode {
protected: protected:
Expression(Zone* zone, int pos) Expression(Zone* zone, int pos)
: AstNode(pos), : AstNode(pos),
zone_(zone),
bounds_(Bounds::Unbounded(zone)), bounds_(Bounds::Unbounded(zone)),
id_(GetNextId(zone)), id_(GetNextId(zone)),
test_id_(GetNextId(zone)) {} test_id_(GetNextId(zone)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; } void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
Zone* zone_;
private: private:
Bounds bounds_; Bounds bounds_;
byte to_boolean_types_; byte to_boolean_types_;
@ -390,7 +394,7 @@ class BreakableStatement : public Statement {
// The labels associated with this statement. May be NULL; // The labels associated with this statement. May be NULL;
// if it is != NULL, guaranteed to contain at least one entry. // if it is != NULL, guaranteed to contain at least one entry.
ZoneStringList* labels() const { return labels_; } ZoneList<const AstRawString*>* labels() const { return labels_; }
// Type testing & conversion. // Type testing & conversion.
virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE { virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE {
@ -410,7 +414,7 @@ class BreakableStatement : public Statement {
protected: protected:
BreakableStatement( BreakableStatement(
Zone* zone, ZoneStringList* labels, Zone* zone, ZoneList<const AstRawString*>* labels,
BreakableType breakable_type, int position) BreakableType breakable_type, int position)
: Statement(zone, position), : Statement(zone, position),
labels_(labels), labels_(labels),
@ -422,7 +426,7 @@ class BreakableStatement : public Statement {
private: private:
ZoneStringList* labels_; ZoneList<const AstRawString*>* labels_;
BreakableType breakable_type_; BreakableType breakable_type_;
Label break_target_; Label break_target_;
const BailoutId entry_id_; const BailoutId entry_id_;
@ -453,7 +457,7 @@ class Block V8_FINAL : public BreakableStatement {
protected: protected:
Block(Zone* zone, Block(Zone* zone,
ZoneStringList* labels, ZoneList<const AstRawString*>* labels,
int capacity, int capacity,
bool is_initializer_block, bool is_initializer_block,
int pos) int pos)
@ -662,18 +666,15 @@ class ModulePath V8_FINAL : public Module {
DECLARE_NODE_TYPE(ModulePath) DECLARE_NODE_TYPE(ModulePath)
Module* module() const { return module_; } Module* module() const { return module_; }
Handle<String> name() const { return name_; } Handle<String> name() const { return name_->string(); }
protected: protected:
ModulePath(Zone* zone, Module* module, Handle<String> name, int pos) ModulePath(Zone* zone, Module* module, const AstRawString* name, int pos)
: Module(zone, pos), : Module(zone, pos), module_(module), name_(name) {}
module_(module),
name_(name) {
}
private: private:
Module* module_; Module* module_;
Handle<String> name_; const AstRawString* name_;
}; };
@ -730,7 +731,7 @@ class IterationStatement : public BreakableStatement {
Label* continue_target() { return &continue_target_; } Label* continue_target() { return &continue_target_; }
protected: protected:
IterationStatement(Zone* zone, ZoneStringList* labels, int pos) IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
body_(NULL), body_(NULL),
osr_entry_id_(GetNextId(zone)) { osr_entry_id_(GetNextId(zone)) {
@ -764,7 +765,7 @@ class DoWhileStatement V8_FINAL : public IterationStatement {
BailoutId BackEdgeId() const { return back_edge_id_; } BailoutId BackEdgeId() const { return back_edge_id_; }
protected: protected:
DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos) DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos), : IterationStatement(zone, labels, pos),
cond_(NULL), cond_(NULL),
continue_id_(GetNextId(zone)), continue_id_(GetNextId(zone)),
@ -801,7 +802,7 @@ class WhileStatement V8_FINAL : public IterationStatement {
BailoutId BodyId() const { return body_id_; } BailoutId BodyId() const { return body_id_; }
protected: protected:
WhileStatement(Zone* zone, ZoneStringList* labels, int pos) WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos), : IterationStatement(zone, labels, pos),
cond_(NULL), cond_(NULL),
may_have_function_literal_(true), may_have_function_literal_(true),
@ -852,7 +853,7 @@ class ForStatement V8_FINAL : public IterationStatement {
void set_loop_variable(Variable* var) { loop_variable_ = var; } void set_loop_variable(Variable* var) { loop_variable_ = var; }
protected: protected:
ForStatement(Zone* zone, ZoneStringList* labels, int pos) ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos), : IterationStatement(zone, labels, pos),
init_(NULL), init_(NULL),
cond_(NULL), cond_(NULL),
@ -894,11 +895,8 @@ class ForEachStatement : public IterationStatement {
Expression* subject() const { return subject_; } Expression* subject() const { return subject_; }
protected: protected:
ForEachStatement(Zone* zone, ZoneStringList* labels, int pos) ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos), : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
each_(NULL),
subject_(NULL) {
}
private: private:
Expression* each_; Expression* each_;
@ -934,7 +932,7 @@ class ForInStatement V8_FINAL : public ForEachStatement,
virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; } virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
protected: protected:
ForInStatement(Zone* zone, ZoneStringList* labels, int pos) ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: ForEachStatement(zone, labels, pos), : ForEachStatement(zone, labels, pos),
for_in_type_(SLOW_FOR_IN), for_in_type_(SLOW_FOR_IN),
for_in_feedback_slot_(kInvalidFeedbackSlot), for_in_feedback_slot_(kInvalidFeedbackSlot),
@ -1004,7 +1002,7 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
BailoutId BackEdgeId() const { return back_edge_id_; } BailoutId BackEdgeId() const { return back_edge_id_; }
protected: protected:
ForOfStatement(Zone* zone, ZoneStringList* labels, int pos) ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: ForEachStatement(zone, labels, pos), : ForEachStatement(zone, labels, pos),
assign_iterator_(NULL), assign_iterator_(NULL),
next_result_(NULL), next_result_(NULL),
@ -1165,7 +1163,7 @@ class SwitchStatement V8_FINAL : public BreakableStatement {
ZoneList<CaseClause*>* cases() const { return cases_; } ZoneList<CaseClause*>* cases() const { return cases_; }
protected: protected:
SwitchStatement(Zone* zone, ZoneStringList* labels, int pos) SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
tag_(NULL), tag_(NULL),
cases_(NULL) { } cases_(NULL) { }
@ -1345,26 +1343,28 @@ class Literal V8_FINAL : public Expression {
DECLARE_NODE_TYPE(Literal) DECLARE_NODE_TYPE(Literal)
virtual bool IsPropertyName() const V8_OVERRIDE { virtual bool IsPropertyName() const V8_OVERRIDE {
if (value_->IsInternalizedString()) { return value_->IsPropertyName();
uint32_t ignored;
return !String::cast(*value_)->AsArrayIndex(&ignored);
}
return false;
} }
Handle<String> AsPropertyName() { Handle<String> AsPropertyName() {
ASSERT(IsPropertyName()); ASSERT(IsPropertyName());
return Handle<String>::cast(value_); return Handle<String>::cast(value());
}
const AstRawString* AsRawPropertyName() {
ASSERT(IsPropertyName());
return value_->AsString();
} }
virtual bool ToBooleanIsTrue() const V8_OVERRIDE { virtual bool ToBooleanIsTrue() const V8_OVERRIDE {
return value_->BooleanValue(); return value()->BooleanValue();
} }
virtual bool ToBooleanIsFalse() const V8_OVERRIDE { 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 // Support for using Literal as a HashMap key. NOTE: Currently, this works
// only for string and number literals! // only for string and number literals!
@ -1379,7 +1379,7 @@ class Literal V8_FINAL : public Expression {
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); } TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
protected: protected:
Literal(Zone* zone, Handle<Object> value, int position) Literal(Zone* zone, const AstValue* value, int position)
: Expression(zone, position), : Expression(zone, position),
value_(value), value_(value),
isolate_(zone->isolate()) { } isolate_(zone->isolate()) { }
@ -1387,7 +1387,7 @@ class Literal V8_FINAL : public Expression {
private: private:
Handle<String> ToString(); Handle<String> ToString();
Handle<Object> value_; const AstValue* value_;
// TODO(dcarney): remove. this is only needed for Match and Hash. // TODO(dcarney): remove. this is only needed for Match and Hash.
Isolate* isolate_; Isolate* isolate_;
}; };
@ -1458,7 +1458,8 @@ class ObjectLiteralProperty V8_FINAL : public ZoneObject {
PROTOTYPE // Property is __proto__. 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_; } Literal* key() { return key_; }
Expression* value() { return value_; } Expression* value() { return value_; }
@ -1557,13 +1558,13 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
public: public:
DECLARE_NODE_TYPE(RegExpLiteral) DECLARE_NODE_TYPE(RegExpLiteral)
Handle<String> pattern() const { return pattern_; } Handle<String> pattern() const { return pattern_->string(); }
Handle<String> flags() const { return flags_; } Handle<String> flags() const { return flags_->string(); }
protected: protected:
RegExpLiteral(Zone* zone, RegExpLiteral(Zone* zone,
Handle<String> pattern, const AstRawString* pattern,
Handle<String> flags, const AstRawString* flags,
int literal_index, int literal_index,
int pos) int pos)
: MaterializedLiteral(zone, literal_index, pos), : MaterializedLiteral(zone, literal_index, pos),
@ -1573,8 +1574,8 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
} }
private: private:
Handle<String> pattern_; const AstRawString* pattern_;
Handle<String> flags_; const AstRawString* flags_;
}; };
@ -1625,15 +1626,12 @@ class VariableProxy V8_FINAL : public Expression {
return var_ == NULL ? true : var_->IsValidReference(); 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 IsArguments() const { return var_ != NULL && var_->is_arguments(); }
bool IsLValue() const { return is_lvalue_; } bool IsLValue() const { return is_lvalue_; }
Handle<String> name() const { return name_; } Handle<String> name() const { return name_->string(); }
const AstRawString* raw_name() const { return name_; }
Variable* var() const { return var_; } Variable* var() const { return var_; }
bool is_this() const { return is_this_; } bool is_this() const { return is_this_; }
Interface* interface() const { return interface_; } Interface* interface() const { return interface_; }
@ -1649,12 +1647,12 @@ class VariableProxy V8_FINAL : public Expression {
VariableProxy(Zone* zone, Variable* var, int position); VariableProxy(Zone* zone, Variable* var, int position);
VariableProxy(Zone* zone, VariableProxy(Zone* zone,
Handle<String> name, const AstRawString* name,
bool is_this, bool is_this,
Interface* interface, Interface* interface,
int position); int position);
Handle<String> name_; const AstRawString* name_;
Variable* var_; // resolved variable, or NULL Variable* var_; // resolved variable, or NULL
bool is_this_; bool is_this_;
bool is_trivial_; bool is_trivial_;
@ -1900,7 +1898,8 @@ class CallRuntime V8_FINAL : public Expression {
public: public:
DECLARE_NODE_TYPE(CallRuntime) DECLARE_NODE_TYPE(CallRuntime)
Handle<String> name() const { return name_; } Handle<String> name() const { return raw_name_->string(); }
const AstRawString* raw_name() const { return raw_name_; }
const Runtime::Function* function() const { return function_; } const Runtime::Function* function() const { return function_; }
ZoneList<Expression*>* arguments() const { return arguments_; } ZoneList<Expression*>* arguments() const { return arguments_; }
bool is_jsruntime() const { return function_ == NULL; } bool is_jsruntime() const { return function_ == NULL; }
@ -1909,17 +1908,17 @@ class CallRuntime V8_FINAL : public Expression {
protected: protected:
CallRuntime(Zone* zone, CallRuntime(Zone* zone,
Handle<String> name, const AstRawString* name,
const Runtime::Function* function, const Runtime::Function* function,
ZoneList<Expression*>* arguments, ZoneList<Expression*>* arguments,
int pos) int pos)
: Expression(zone, pos), : Expression(zone, pos),
name_(name), raw_name_(name),
function_(function), function_(function),
arguments_(arguments) { } arguments_(arguments) { }
private: private:
Handle<String> name_; const AstRawString* raw_name_;
const Runtime::Function* function_; const Runtime::Function* function_;
ZoneList<Expression*>* arguments_; ZoneList<Expression*>* arguments_;
}; };
@ -2313,7 +2312,8 @@ class FunctionLiteral V8_FINAL : public Expression {
DECLARE_NODE_TYPE(FunctionLiteral) DECLARE_NODE_TYPE(FunctionLiteral)
Handle<String> name() const { return name_; } Handle<String> name() const { return raw_name_->string(); }
const AstRawString* raw_name() const { return raw_name_; }
Scope* scope() const { return scope_; } Scope* scope() const { return scope_; }
ZoneList<Statement*>* body() const { return body_; } ZoneList<Statement*>* body() const { return body_; }
void set_function_token_position(int pos) { function_token_position_ = pos; } void set_function_token_position(int pos) { function_token_position_ = pos; }
@ -2336,13 +2336,37 @@ class FunctionLiteral V8_FINAL : public Expression {
void InitializeSharedInfo(Handle<Code> code); void InitializeSharedInfo(Handle<Code> code);
Handle<String> debug_name() const { 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(); 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) { void set_inferred_name(Handle<String> inferred_name) {
ASSERT(!inferred_name.is_null());
inferred_name_ = 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) {
ASSERT(raw_inferred_name != NULL);
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. // shared_info may be null if it's not cached in full code.
@ -2389,7 +2413,8 @@ class FunctionLiteral V8_FINAL : public Expression {
protected: protected:
FunctionLiteral(Zone* zone, FunctionLiteral(Zone* zone,
Handle<String> name, const AstRawString* name,
AstValueFactory* ast_value_factory,
Scope* scope, Scope* scope,
ZoneList<Statement*>* body, ZoneList<Statement*>* body,
int materialized_literal_count, int materialized_literal_count,
@ -2403,10 +2428,10 @@ class FunctionLiteral V8_FINAL : public Expression {
IsGeneratorFlag is_generator, IsGeneratorFlag is_generator,
int position) int position)
: Expression(zone, position), : Expression(zone, position),
name_(name), raw_name_(name),
scope_(scope), scope_(scope),
body_(body), body_(body),
inferred_name_(zone->isolate()->factory()->empty_string()), raw_inferred_name_(ast_value_factory->empty_string()),
dont_optimize_reason_(kNoReason), dont_optimize_reason_(kNoReason),
materialized_literal_count_(materialized_literal_count), materialized_literal_count_(materialized_literal_count),
expected_property_count_(expected_property_count), expected_property_count_(expected_property_count),
@ -2424,10 +2449,12 @@ class FunctionLiteral V8_FINAL : public Expression {
} }
private: private:
const AstRawString* raw_name_;
Handle<String> name_; Handle<String> name_;
Handle<SharedFunctionInfo> shared_info_; Handle<SharedFunctionInfo> shared_info_;
Scope* scope_; Scope* scope_;
ZoneList<Statement*>* body_; ZoneList<Statement*>* body_;
const AstString* raw_inferred_name_;
Handle<String> inferred_name_; Handle<String> inferred_name_;
AstProperties ast_properties_; AstProperties ast_properties_;
BailoutReason dont_optimize_reason_; BailoutReason dont_optimize_reason_;
@ -2453,16 +2480,16 @@ class NativeFunctionLiteral V8_FINAL : public Expression {
public: public:
DECLARE_NODE_TYPE(NativeFunctionLiteral) DECLARE_NODE_TYPE(NativeFunctionLiteral)
Handle<String> name() const { return name_; } Handle<String> name() const { return name_->string(); }
v8::Extension* extension() const { return extension_; } v8::Extension* extension() const { return extension_; }
protected: protected:
NativeFunctionLiteral( NativeFunctionLiteral(Zone* zone, const AstRawString* name,
Zone* zone, Handle<String> name, v8::Extension* extension, int pos) v8::Extension* extension, int pos)
: Expression(zone, pos), name_(name), extension_(extension) {} : Expression(zone, pos), name_(name), extension_(extension) {}
private: private:
Handle<String> name_; const AstRawString* name_;
v8::Extension* extension_; v8::Extension* extension_;
}; };
@ -2954,7 +2981,8 @@ class AstNullVisitor BASE_EMBEDDED {
template<class Visitor> template<class Visitor>
class AstNodeFactory V8_FINAL BASE_EMBEDDED { class AstNodeFactory V8_FINAL BASE_EMBEDDED {
public: 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_; } Visitor* visitor() { return &visitor_; }
@ -3018,8 +3046,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(ModuleVariable, module) VISIT_AND_RETURN(ModuleVariable, module)
} }
ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) { ModulePath* NewModulePath(Module* origin, const AstRawString* name, int pos) {
ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos); ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos);
VISIT_AND_RETURN(ModulePath, module) VISIT_AND_RETURN(ModulePath, module)
} }
@ -3028,7 +3056,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(ModuleUrl, module) VISIT_AND_RETURN(ModuleUrl, module)
} }
Block* NewBlock(ZoneStringList* labels, Block* NewBlock(ZoneList<const AstRawString*>* labels,
int capacity, int capacity,
bool is_initializer_block, bool is_initializer_block,
int pos) { int pos) {
@ -3038,7 +3066,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
} }
#define STATEMENT_WITH_LABELS(NodeType) \ #define STATEMENT_WITH_LABELS(NodeType) \
NodeType* New##NodeType(ZoneStringList* labels, int pos) { \ NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \
NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \ NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \
VISIT_AND_RETURN(NodeType, stmt); \ VISIT_AND_RETURN(NodeType, stmt); \
} }
@ -3049,7 +3077,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
#undef STATEMENT_WITH_LABELS #undef STATEMENT_WITH_LABELS
ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode, ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
ZoneStringList* labels, ZoneList<const AstRawString*>* labels,
int pos) { int pos) {
switch (visit_mode) { switch (visit_mode) {
case ForEachStatement::ENUMERATE: { case ForEachStatement::ENUMERATE: {
@ -3146,14 +3174,60 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(CaseClause, clause) VISIT_AND_RETURN(CaseClause, clause)
} }
Literal* NewLiteral(Handle<Object> handle, int pos) { Literal* NewStringLiteral(const AstRawString* string, int pos) {
Literal* lit = new(zone_) Literal(zone_, handle, 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) VISIT_AND_RETURN(Literal, lit)
} }
Literal* NewNumberLiteral(double number, int pos) { Literal* NewNumberLiteral(double number, int pos) {
return NewLiteral( Literal* lit = new (zone_)
zone_->isolate()->factory()->NewNumber(number, TENURED), pos); 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 AstRawString*>* 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* NewObjectLiteral(
@ -3170,7 +3244,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key, ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
Expression* value) { 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, ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
@ -3178,12 +3253,12 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
int pos) { int pos) {
ObjectLiteral::Property* prop = ObjectLiteral::Property* prop =
new(zone_) ObjectLiteral::Property(zone_, is_getter, value); 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. return prop; // Not an AST node, will not be visited.
} }
RegExpLiteral* NewRegExpLiteral(Handle<String> pattern, RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern,
Handle<String> flags, const AstRawString* flags,
int literal_index, int literal_index,
int pos) { int pos) {
RegExpLiteral* lit = RegExpLiteral* lit =
@ -3205,7 +3280,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(VariableProxy, proxy) VISIT_AND_RETURN(VariableProxy, proxy)
} }
VariableProxy* NewVariableProxy(Handle<String> name, VariableProxy* NewVariableProxy(const AstRawString* name,
bool is_this, bool is_this,
Interface* interface = Interface::NewValue(), Interface* interface = Interface::NewValue(),
int position = RelocInfo::kNoPosition) { int position = RelocInfo::kNoPosition) {
@ -3233,7 +3308,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(CallNew, call) VISIT_AND_RETURN(CallNew, call)
} }
CallRuntime* NewCallRuntime(Handle<String> name, CallRuntime* NewCallRuntime(const AstRawString* name,
const Runtime::Function* function, const Runtime::Function* function,
ZoneList<Expression*>* arguments, ZoneList<Expression*>* arguments,
int pos) { int pos) {
@ -3311,7 +3386,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
} }
FunctionLiteral* NewFunctionLiteral( FunctionLiteral* NewFunctionLiteral(
Handle<String> name, const AstRawString* name,
AstValueFactory* ast_value_factory,
Scope* scope, Scope* scope,
ZoneList<Statement*>* body, ZoneList<Statement*>* body,
int materialized_literal_count, int materialized_literal_count,
@ -3325,7 +3401,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
FunctionLiteral::IsGeneratorFlag is_generator, FunctionLiteral::IsGeneratorFlag is_generator,
int position) { int position) {
FunctionLiteral* lit = new(zone_) FunctionLiteral( FunctionLiteral* lit = new(zone_) FunctionLiteral(
zone_, name, scope, body, zone_, name, ast_value_factory, scope, body,
materialized_literal_count, expected_property_count, handler_count, materialized_literal_count, expected_property_count, handler_count,
parameter_count, function_type, has_duplicate_parameters, is_function, parameter_count, function_type, has_duplicate_parameters, is_function,
is_parenthesized, is_generator, position); is_parenthesized, is_generator, position);
@ -3337,7 +3413,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
} }
NativeFunctionLiteral* NewNativeFunctionLiteral( NativeFunctionLiteral* NewNativeFunctionLiteral(
Handle<String> name, v8::Extension* extension, int pos) { const AstRawString* name, v8::Extension* extension,
int pos) {
NativeFunctionLiteral* lit = NativeFunctionLiteral* lit =
new(zone_) NativeFunctionLiteral(zone_, name, extension, pos); new(zone_) NativeFunctionLiteral(zone_, name, extension, pos);
VISIT_AND_RETURN(NativeFunctionLiteral, lit) VISIT_AND_RETURN(NativeFunctionLiteral, lit)
@ -3353,6 +3430,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
private: private:
Zone* zone_; Zone* zone_;
Visitor visitor_; Visitor visitor_;
AstValueFactory* ast_value_factory_;
}; };

View File

@ -38,7 +38,9 @@ CompilationInfo::CompilationInfo(Handle<Script> script,
osr_ast_id_(BailoutId::None()), osr_ast_id_(BailoutId::None()),
parameter_count_(0), parameter_count_(0),
this_has_uses_(true), this_has_uses_(true),
optimization_id_(-1) { optimization_id_(-1),
ast_value_factory_(NULL),
ast_value_factory_owned_(false) {
Initialize(script->GetIsolate(), BASE, zone); Initialize(script->GetIsolate(), BASE, zone);
} }
@ -51,7 +53,9 @@ CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
osr_ast_id_(BailoutId::None()), osr_ast_id_(BailoutId::None()),
parameter_count_(0), parameter_count_(0),
this_has_uses_(true), this_has_uses_(true),
optimization_id_(-1) { optimization_id_(-1),
ast_value_factory_(NULL),
ast_value_factory_owned_(false) {
Initialize(script_->GetIsolate(), BASE, zone); Initialize(script_->GetIsolate(), BASE, zone);
} }
@ -66,7 +70,9 @@ CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
osr_ast_id_(BailoutId::None()), osr_ast_id_(BailoutId::None()),
parameter_count_(0), parameter_count_(0),
this_has_uses_(true), this_has_uses_(true),
optimization_id_(-1) { optimization_id_(-1),
ast_value_factory_(NULL),
ast_value_factory_owned_(false) {
Initialize(script_->GetIsolate(), BASE, zone); Initialize(script_->GetIsolate(), BASE, zone);
} }
@ -78,7 +84,9 @@ CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
osr_ast_id_(BailoutId::None()), osr_ast_id_(BailoutId::None()),
parameter_count_(0), parameter_count_(0),
this_has_uses_(true), this_has_uses_(true),
optimization_id_(-1) { optimization_id_(-1),
ast_value_factory_(NULL),
ast_value_factory_owned_(false) {
Initialize(isolate, STUB, zone); Initialize(isolate, STUB, zone);
code_stub_ = stub; code_stub_ = stub;
} }
@ -131,6 +139,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
CompilationInfo::~CompilationInfo() { CompilationInfo::~CompilationInfo() {
delete deferred_handles_; delete deferred_handles_;
delete no_frame_ranges_; delete no_frame_ranges_;
if (ast_value_factory_owned_) delete ast_value_factory_;
#ifdef DEBUG #ifdef DEBUG
// Check that no dependent maps have been added or added dependent maps have // Check that no dependent maps have been added or added dependent maps have
// been rolled back or committed. // been rolled back or committed.

View File

@ -12,6 +12,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class AstValueFactory;
class ScriptData; class ScriptData;
class HydrogenCodeStub; class HydrogenCodeStub;
@ -321,6 +322,13 @@ class CompilationInfo {
int optimization_id() const { return optimization_id_; } int optimization_id() const { return optimization_id_; }
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
void SetAstValueFactory(AstValueFactory* ast_value_factory,
bool owned = true) {
ast_value_factory_ = ast_value_factory;
ast_value_factory_owned_ = owned;
}
protected: protected:
CompilationInfo(Handle<Script> script, CompilationInfo(Handle<Script> script,
Zone* zone); Zone* zone);
@ -464,6 +472,9 @@ class CompilationInfo {
int optimization_id_; int optimization_id_;
AstValueFactory* ast_value_factory_;
bool ast_value_factory_owned_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo); DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
}; };

View File

@ -5,14 +5,16 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/ast.h" #include "src/ast.h"
#include "src/ast-value-factory.h"
#include "src/func-name-inferrer.h" #include "src/func-name-inferrer.h"
#include "src/list-inl.h" #include "src/list-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone) FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
: isolate_(isolate), Zone* zone)
: ast_value_factory_(ast_value_factory),
entries_stack_(10, zone), entries_stack_(10, zone),
names_stack_(5, zone), names_stack_(5, zone),
funcs_to_infer_(4, zone), funcs_to_infer_(4, zone),
@ -20,40 +22,36 @@ FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
} }
void FuncNameInferrer::PushEnclosingName(Handle<String> name) { void FuncNameInferrer::PushEnclosingName(const AstRawString* name) {
// Enclosing name is a name of a constructor function. To check // Enclosing name is a name of a constructor function. To check
// that it is really a constructor, we check that it is not empty // that it is really a constructor, we check that it is not empty
// and starts with a capital letter. // and starts with a capital letter.
if (name->length() > 0 && Runtime::IsUpperCaseChar( if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
isolate()->runtime_state(), name->Get(0))) {
names_stack_.Add(Name(name, kEnclosingConstructorName), zone()); names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
} }
} }
void FuncNameInferrer::PushLiteralName(Handle<String> name) { void FuncNameInferrer::PushLiteralName(const AstRawString* name) {
if (IsOpen() && if (IsOpen() && name != ast_value_factory_->prototype_string()) {
!String::Equals(isolate()->factory()->prototype_string(), name)) {
names_stack_.Add(Name(name, kLiteralName), zone()); names_stack_.Add(Name(name, kLiteralName), zone());
} }
} }
void FuncNameInferrer::PushVariableName(Handle<String> name) { void FuncNameInferrer::PushVariableName(const AstRawString* name) {
if (IsOpen() && if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
!String::Equals(isolate()->factory()->dot_result_string(), name)) {
names_stack_.Add(Name(name, kVariableName), zone()); names_stack_.Add(Name(name, kVariableName), zone());
} }
} }
Handle<String> FuncNameInferrer::MakeNameFromStack() { const AstString* FuncNameInferrer::MakeNameFromStack() {
return MakeNameFromStackHelper(0, isolate()->factory()->empty_string()); return MakeNameFromStackHelper(0, ast_value_factory_->empty_string());
} }
const AstString* FuncNameInferrer::MakeNameFromStackHelper(
Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos, int pos, const AstString* prev) {
Handle<String> prev) {
if (pos >= names_stack_.length()) return prev; if (pos >= names_stack_.length()) return prev;
if (pos < names_stack_.length() - 1 && if (pos < names_stack_.length() - 1 &&
names_stack_.at(pos).type == kVariableName && names_stack_.at(pos).type == kVariableName &&
@ -62,12 +60,11 @@ Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
return MakeNameFromStackHelper(pos + 1, prev); return MakeNameFromStackHelper(pos + 1, prev);
} else { } else {
if (prev->length() > 0) { if (prev->length() > 0) {
Handle<String> name = names_stack_.at(pos).name; const AstRawString* name = names_stack_.at(pos).name;
if (prev->length() + name->length() + 1 > String::kMaxLength) return prev; if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
Factory* factory = isolate()->factory(); const AstConsString* curr = ast_value_factory_->NewConsString(
Handle<String> curr = ast_value_factory_->dot_string(), name);
factory->NewConsString(factory->dot_string(), name).ToHandleChecked(); curr = ast_value_factory_->NewConsString(prev, curr);
curr = factory->NewConsString(prev, curr).ToHandleChecked();
return MakeNameFromStackHelper(pos + 1, curr); return MakeNameFromStackHelper(pos + 1, curr);
} else { } else {
return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name); return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
@ -77,9 +74,9 @@ Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
void FuncNameInferrer::InferFunctionsNames() { void FuncNameInferrer::InferFunctionsNames() {
Handle<String> func_name = MakeNameFromStack(); const AstString* func_name = MakeNameFromStack();
for (int i = 0; i < funcs_to_infer_.length(); ++i) { 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); funcs_to_infer_.Rewind(0);
} }

View File

@ -11,8 +11,10 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class AstRawString;
class AstString;
class AstValueFactory;
class FunctionLiteral; class FunctionLiteral;
class Isolate;
// FuncNameInferrer is a stateful class that is used to perform name // FuncNameInferrer is a stateful class that is used to perform name
// inference for anonymous functions during static analysis of source code. // inference for anonymous functions during static analysis of source code.
@ -26,13 +28,13 @@ class Isolate;
// a name. // a name.
class FuncNameInferrer : public ZoneObject { class FuncNameInferrer : public ZoneObject {
public: public:
FuncNameInferrer(Isolate* isolate, Zone* zone); FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
// Returns whether we have entered name collection state. // Returns whether we have entered name collection state.
bool IsOpen() const { return !entries_stack_.is_empty(); } bool IsOpen() const { return !entries_stack_.is_empty(); }
// Pushes an enclosing the name of enclosing function onto names stack. // Pushes an enclosing the name of enclosing function onto names stack.
void PushEnclosingName(Handle<String> name); void PushEnclosingName(const AstRawString* name);
// Enters name collection state. // Enters name collection state.
void Enter() { void Enter() {
@ -40,9 +42,9 @@ class FuncNameInferrer : public ZoneObject {
} }
// Pushes an encountered name onto names stack when in collection state. // Pushes an encountered name onto names stack when in collection state.
void PushLiteralName(Handle<String> name); void PushLiteralName(const AstRawString* name);
void PushVariableName(Handle<String> name); void PushVariableName(const AstRawString* name);
// Adds a function to infer name for. // Adds a function to infer name for.
void AddFunction(FunctionLiteral* func_to_infer) { void AddFunction(FunctionLiteral* func_to_infer) {
@ -80,24 +82,24 @@ class FuncNameInferrer : public ZoneObject {
kVariableName kVariableName
}; };
struct Name { struct Name {
Name(Handle<String> name, NameType type) : name(name), type(type) { } Name(const AstRawString* name, NameType type) : name(name), type(type) {}
Handle<String> name; const AstRawString* name;
NameType type; NameType type;
}; };
Isolate* isolate() { return isolate_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
// Constructs a full name in dotted notation from gathered names. // Constructs a full name in dotted notation from gathered names.
Handle<String> MakeNameFromStack(); const AstString* MakeNameFromStack();
// A helper function for MakeNameFromStack. // A helper function for MakeNameFromStack.
Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev); const AstString* MakeNameFromStackHelper(int pos,
const AstString* prev);
// Performs name inferring for added functions. // Performs name inferring for added functions.
void InferFunctionsNames(); void InferFunctionsNames();
Isolate* isolate_; AstValueFactory* ast_value_factory_;
ZoneList<int> entries_stack_; ZoneList<int> entries_stack_;
ZoneList<Name> names_stack_; ZoneList<Name> names_stack_;
ZoneList<FunctionLiteral*> funcs_to_infer_; ZoneList<FunctionLiteral*> funcs_to_infer_;

View File

@ -277,16 +277,11 @@ namespace internal {
V(constructor_string, "constructor") \ V(constructor_string, "constructor") \
V(dot_result_string, ".result") \ V(dot_result_string, ".result") \
V(dot_for_string, ".for.") \ 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(eval_string, "eval") \
V(empty_string, "") \ V(empty_string, "") \
V(function_string, "function") \ V(function_string, "function") \
V(length_string, "length") \ V(length_string, "length") \
V(module_string, "module") \
V(name_string, "name") \ V(name_string, "name") \
V(native_string, "native") \
V(null_string, "null") \ V(null_string, "null") \
V(number_string, "number") \ V(number_string, "number") \
V(Number_string, "Number") \ V(Number_string, "Number") \
@ -312,7 +307,6 @@ namespace internal {
V(private_api_string, "private_api") \ V(private_api_string, "private_api") \
V(private_intern_string, "private_intern") \ V(private_intern_string, "private_intern") \
V(Date_string, "Date") \ V(Date_string, "Date") \
V(this_string, "this") \
V(to_string_string, "toString") \ V(to_string_string, "toString") \
V(char_at_string, "CharAt") \ V(char_at_string, "CharAt") \
V(undefined_string, "undefined") \ V(undefined_string, "undefined") \
@ -335,19 +329,13 @@ namespace internal {
V(cell_value_string, "%cell_value") \ V(cell_value_string, "%cell_value") \
V(function_class_string, "Function") \ V(function_class_string, "Function") \
V(illegal_argument_string, "illegal argument") \ 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(space_string, " ") \
V(exec_string, "exec") \ V(exec_string, "exec") \
V(zero_string, "0") \ V(zero_string, "0") \
V(global_eval_string, "GlobalEval") \ V(global_eval_string, "GlobalEval") \
V(identity_hash_string, "v8::IdentityHash") \ V(identity_hash_string, "v8::IdentityHash") \
V(closure_string, "(closure)") \ V(closure_string, "(closure)") \
V(use_strict_string, "use strict") \
V(dot_string, ".") \ V(dot_string, ".") \
V(anonymous_function_string, "(anonymous function)") \
V(compare_ic_string, "==") \ V(compare_ic_string, "==") \
V(strict_compare_ic_string, "===") \ V(strict_compare_ic_string, "===") \
V(infinity_string, "Infinity") \ V(infinity_string, "Infinity") \

View File

@ -7626,6 +7626,9 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
// Parse and allocate variables. // Parse and allocate variables.
CompilationInfo target_info(target, zone()); CompilationInfo target_info(target, zone());
// Use the same AstValueFactory for creating strings in the sub-compilation
// step, but don't transfer ownership to target_info.
target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
Handle<SharedFunctionInfo> target_shared(target->shared()); Handle<SharedFunctionInfo> target_shared(target->shared());
if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
if (target_info.isolate()->has_pending_exception()) { if (target_info.isolate()->has_pending_exception()) {

View File

@ -9,15 +9,6 @@
namespace v8 { namespace v8 {
namespace internal { 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) { Interface* Interface::Lookup(Handle<String> name, Zone* zone) {
ASSERT(IsModule()); ASSERT(IsModule());
ZoneHashMap* map = Chase()->exports_; ZoneHashMap* map = Chase()->exports_;
@ -47,8 +38,8 @@ int Nesting::current_ = 0;
#endif #endif
void Interface::DoAdd( void Interface::DoAdd(const void* name, uint32_t hash, Interface* interface,
void* name, uint32_t hash, Interface* interface, Zone* zone, bool* ok) { Zone* zone, bool* ok) {
MakeModule(ok); MakeModule(ok);
if (!*ok) return; if (!*ok) return;
@ -57,8 +48,9 @@ void Interface::DoAdd(
PrintF("%*s# Adding...\n", Nesting::current(), ""); PrintF("%*s# Adding...\n", Nesting::current(), "");
PrintF("%*sthis = ", Nesting::current(), ""); PrintF("%*sthis = ", Nesting::current(), "");
this->Print(Nesting::current()); this->Print(Nesting::current());
PrintF("%*s%s : ", Nesting::current(), "", const AstRawString* symbol = static_cast<const AstRawString*>(name);
(*static_cast<String**>(name))->ToAsciiArray()); PrintF("%*s%.*s : ", Nesting::current(), "", symbol->length(),
symbol->raw_data());
interface->Print(Nesting::current()); interface->Print(Nesting::current());
} }
#endif #endif
@ -68,10 +60,12 @@ void Interface::DoAdd(
if (*map == NULL) { if (*map == NULL) {
*map = new(zone->New(sizeof(ZoneHashMap))) *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) { if (p == NULL) {
// This didn't have name but was frozen already, that's an error. // This didn't have name but was frozen already, that's an error.
*ok = false; *ok = false;

View File

@ -5,6 +5,7 @@
#ifndef V8_INTERFACE_H_ #ifndef V8_INTERFACE_H_
#define V8_INTERFACE_H_ #define V8_INTERFACE_H_
#include "src/ast-value-factory.h"
#include "src/zone-inl.h" // For operator new. #include "src/zone-inl.h" // For operator new.
namespace v8 { namespace v8 {
@ -59,8 +60,9 @@ class Interface : public ZoneObject {
// Add a name to the list of exports. If it already exists, unify with // Add a name to the list of exports. If it already exists, unify with
// interface, otherwise insert unless this is closed. // interface, otherwise insert unless this is closed.
void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) { void Add(const AstRawString* name, Interface* interface, Zone* zone,
DoAdd(name.location(), name->Hash(), interface, zone, ok); bool* ok) {
DoAdd(name, name->hash(), interface, zone, ok);
} }
// Unify with another interface. If successful, both interface objects will // Unify with another interface. If successful, both interface objects will
@ -146,9 +148,9 @@ class Interface : public ZoneObject {
class Iterator { class Iterator {
public: public:
bool done() const { return entry_ == NULL; } bool done() const { return entry_ == NULL; }
Handle<String> name() const { const AstRawString* name() const {
ASSERT(!done()); ASSERT(!done());
return Handle<String>(*static_cast<String**>(entry_->key)); return static_cast<const AstRawString*>(entry_->key);
} }
Interface* interface() const { Interface* interface() const {
ASSERT(!done()); ASSERT(!done());
@ -207,7 +209,7 @@ class Interface : public ZoneObject {
return result; 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); bool* ok);
void DoUnify(Interface* that, bool* ok, Zone* zone); void DoUnify(Interface* that, bool* ok, Zone* zone);
}; };

View File

@ -1701,22 +1701,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
bool HeapNumber::HeapNumberBooleanValue() { bool HeapNumber::HeapNumberBooleanValue() {
// NaN, +0, and -0 should return the false object return DoubleToBoolean(value());
#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;
} }
@ -9362,29 +9347,7 @@ bool String::ComputeArrayIndex(uint32_t* index) {
if (length == 0 || length > kMaxArrayIndexSize) return false; if (length == 0 || length > kMaxArrayIndexSize) return false;
ConsStringIteratorOp op; ConsStringIteratorOp op;
StringCharacterStream stream(this, &op); StringCharacterStream stream(this, &op);
uint16_t ch = stream.GetNext(); return StringToArrayIndex(&stream, index);
// 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;
} }

File diff suppressed because it is too large Load Diff

View File

@ -389,7 +389,7 @@ class ParserTraits {
typedef v8::internal::Zone Zone; typedef v8::internal::Zone Zone;
// Return types for traversing functions. // Return types for traversing functions.
typedef Handle<String> Identifier; typedef const AstRawString* Identifier;
typedef v8::internal::Expression* Expression; typedef v8::internal::Expression* Expression;
typedef Yield* YieldExpression; typedef Yield* YieldExpression;
typedef v8::internal::FunctionLiteral* FunctionLiteral; typedef v8::internal::FunctionLiteral* FunctionLiteral;
@ -421,29 +421,29 @@ class ParserTraits {
} }
// Helper functions for recursive descent. // Helper functions for recursive descent.
bool IsEvalOrArguments(Handle<String> identifier) const; bool IsEvalOrArguments(const AstRawString* identifier) const;
// Returns true if the expression is of type "this.foo". // Returns true if the expression is of type "this.foo".
static bool IsThisProperty(Expression* expression); static bool IsThisProperty(Expression* expression);
static bool IsIdentifier(Expression* expression); static bool IsIdentifier(Expression* expression);
static Handle<String> AsIdentifier(Expression* expression) { static const AstRawString* AsIdentifier(Expression* expression) {
ASSERT(IsIdentifier(expression)); ASSERT(IsIdentifier(expression));
return expression->AsVariableProxy()->name(); return expression->AsVariableProxy()->raw_name();
} }
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) { static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
return ObjectLiteral::IsBoilerplateProperty(property); return ObjectLiteral::IsBoilerplateProperty(property);
} }
static bool IsArrayIndex(Handle<String> string, uint32_t* index) { static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
return !string.is_null() && string->AsArrayIndex(index); return string->AsArrayIndex(index);
} }
// Functions for encapsulating the differences between parsing and preparsing; // Functions for encapsulating the differences between parsing and preparsing;
// operations interleaved with the recursive descent. // operations interleaved with the recursive descent.
static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) { static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
fni->PushLiteralName(id); fni->PushLiteralName(id);
} }
void PushPropertyName(FuncNameInferrer* fni, Expression* expression); void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
@ -501,16 +501,17 @@ class ParserTraits {
// type. The first argument may be null (in the handle sense) in // type. The first argument may be null (in the handle sense) in
// which case no arguments are passed to the constructor. // which case no arguments are passed to the constructor.
Expression* NewThrowSyntaxError( Expression* NewThrowSyntaxError(
const char* type, Handle<Object> arg, int pos); const char* type, const AstRawString* arg, int pos);
// Generate AST node that throws a TypeError with the given // Generate AST node that throws a TypeError with the given
// type. Both arguments must be non-null (in the handle sense). // 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 AstRawString* arg,
int pos);
// Generic AST generator for throwing errors from compiled code. // Generic AST generator for throwing errors from compiled code.
Expression* NewThrowError( Expression* NewThrowError(
Handle<String> constructor, const char* type, const AstRawString* constructor, const char* type,
Vector<Handle<Object> > arguments, int pos); const AstRawString* arg, int pos);
// Reporting errors. // Reporting errors.
void ReportMessageAt(Scanner::Location source_location, void ReportMessageAt(Scanner::Location source_location,
@ -518,16 +519,19 @@ class ParserTraits {
const char* arg = NULL, const char* arg = NULL,
bool is_reference_error = false); bool is_reference_error = false);
void ReportMessage(const char* message, void ReportMessage(const char* message,
MaybeHandle<String> arg, const char* arg = NULL,
bool is_reference_error = false);
void ReportMessage(const char* message,
const AstRawString* arg,
bool is_reference_error = false); bool is_reference_error = false);
void ReportMessageAt(Scanner::Location source_location, void ReportMessageAt(Scanner::Location source_location,
const char* message, const char* message,
MaybeHandle<String> arg, const AstRawString* arg,
bool is_reference_error = false); bool is_reference_error = false);
// "null" return type creators. // "null" return type creators.
static Handle<String> EmptyIdentifier() { static const AstRawString* EmptyIdentifier() {
return Handle<String>(); return NULL;
} }
static Expression* EmptyExpression() { static Expression* EmptyExpression() {
return NULL; return NULL;
@ -545,16 +549,16 @@ class ParserTraits {
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
// Producing data during the recursive descent. // Producing data during the recursive descent.
Handle<String> GetSymbol(Scanner* scanner = NULL); const AstRawString* GetSymbol(Scanner* scanner);
Handle<String> NextLiteralString(Scanner* scanner, const AstRawString* GetNextSymbol(Scanner* scanner);
PretenureFlag tenured);
Expression* ThisExpression(Scope* scope, Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
Literal* ExpressionFromLiteral( Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner, Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier( Expression* ExpressionFromIdentifier(
Handle<String> name, int pos, Scope* scope, const AstRawString* name, int pos, Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromString( Expression* ExpressionFromString(
int pos, Scanner* scanner, int pos, Scanner* scanner,
@ -572,7 +576,7 @@ class ParserTraits {
// Temporary glue; these functions will move to ParserBase. // Temporary glue; these functions will move to ParserBase.
Expression* ParseV8Intrinsic(bool* ok); Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
Handle<String> name, const AstRawString* name,
Scanner::Location function_name_location, Scanner::Location function_name_location,
bool name_is_strict_reserved, bool name_is_strict_reserved,
bool is_generator, bool is_generator,
@ -644,7 +648,7 @@ class Parser : public ParserBase<ParserTraits> {
Handle<String> source); Handle<String> source);
// Report syntax error // Report syntax error
void ReportInvalidCachedData(Handle<String> name, bool* ok); void ReportInvalidCachedData(const AstRawString* name, bool* ok);
void SetCachedData(ScriptData** data, void SetCachedData(ScriptData** data,
CachedDataMode cached_data_mode) { CachedDataMode cached_data_mode) {
@ -671,8 +675,10 @@ class Parser : public ParserBase<ParserTraits> {
// for failure at the call sites. // for failure at the call sites.
void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token, void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
bool is_eval, bool is_global, bool* ok); bool is_eval, bool is_global, bool* ok);
Statement* ParseModuleElement(ZoneStringList* labels, bool* ok); Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
Statement* ParseModuleDeclaration(ZoneStringList* names, bool* ok); bool* ok);
Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
Module* ParseModule(bool* ok); Module* ParseModule(bool* ok);
Module* ParseModuleLiteral(bool* ok); Module* ParseModuleLiteral(bool* ok);
Module* ParseModulePath(bool* ok); Module* ParseModulePath(bool* ok);
@ -681,38 +687,45 @@ class Parser : public ParserBase<ParserTraits> {
Module* ParseModuleSpecifier(bool* ok); Module* ParseModuleSpecifier(bool* ok);
Block* ParseImportDeclaration(bool* ok); Block* ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok); Statement* ParseExportDeclaration(bool* ok);
Statement* ParseBlockElement(ZoneStringList* labels, bool* ok); Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseStatement(ZoneStringList* labels, bool* ok); Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok); Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseNativeDeclaration(bool* ok); Statement* ParseNativeDeclaration(bool* ok);
Block* ParseBlock(ZoneStringList* labels, bool* ok); Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context, Block* ParseVariableStatement(VariableDeclarationContext var_context,
ZoneStringList* names, ZoneList<const AstRawString*>* names,
bool* ok); bool* ok);
Block* ParseVariableDeclarations(VariableDeclarationContext var_context, Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props, VariableDeclarationProperties* decl_props,
ZoneStringList* names, ZoneList<const AstRawString*>* names,
Handle<String>* out, const AstRawString** out,
bool* ok); bool* ok);
Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels, Statement* ParseExpressionOrLabelledStatement(
bool* ok); ZoneList<const AstRawString*>* labels, bool* ok);
IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok); IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseContinueStatement(bool* ok); Statement* ParseContinueStatement(bool* ok);
Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok); Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseReturnStatement(bool* ok); Statement* ParseReturnStatement(bool* ok);
Statement* ParseWithStatement(ZoneStringList* labels, bool* ok); Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok); CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok); SwitchStatement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok); bool* ok);
WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok); DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
Statement* ParseForStatement(ZoneStringList* labels, bool* ok); bool* ok);
WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseThrowStatement(bool* ok); Statement* ParseThrowStatement(bool* ok);
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value); Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
TryStatement* ParseTryStatement(bool* ok); TryStatement* ParseTryStatement(bool* ok);
DebuggerStatement* ParseDebuggerStatement(bool* ok); DebuggerStatement* ParseDebuggerStatement(bool* ok);
// Support for hamony block scoped bindings. // Support for hamony block scoped bindings.
Block* ParseScopedBlock(ZoneStringList* labels, bool* ok); Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
// Initialize the components of a for-in / for-of statement. // Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt, void InitializeForEachStatement(ForEachStatement* stmt,
@ -720,12 +733,12 @@ class Parser : public ParserBase<ParserTraits> {
Expression* subject, Expression* subject,
Statement* body); Statement* body);
Statement* DesugarLetBindingsInForStatement( Statement* DesugarLetBindingsInForStatement(
Scope* inner_scope, ZoneStringList* names, ForStatement* loop, Scope* inner_scope, ZoneList<const AstRawString*>* names,
Statement* init, Expression* cond, Statement* next, Statement* body, ForStatement* loop, Statement* init, Expression* cond, Statement* next,
bool* ok); Statement* body, bool* ok);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
Handle<String> name, const AstRawString* name,
Scanner::Location function_name_location, Scanner::Location function_name_location,
bool name_is_strict_reserved, bool name_is_strict_reserved,
bool is_generator, bool is_generator,
@ -754,14 +767,14 @@ class Parser : public ParserBase<ParserTraits> {
void CheckConflictingVarDeclarations(Scope* scope, bool* ok); void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support // Parser support
VariableProxy* NewUnresolved(Handle<String> name, VariableProxy* NewUnresolved(const AstRawString* name,
VariableMode mode, VariableMode mode,
Interface* interface); Interface* interface);
void Declare(Declaration* declaration, bool resolve, bool* ok); void Declare(Declaration* declaration, bool resolve, bool* ok);
bool TargetStackContainsLabel(Handle<String> label); bool TargetStackContainsLabel(const AstRawString* label);
BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok); BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok); IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
void RegisterTargetUse(Label* target, Target* stop); void RegisterTargetUse(Label* target, Target* stop);
@ -771,7 +784,7 @@ class Parser : public ParserBase<ParserTraits> {
// Skip over a lazy function, either using cached data if we have it, or // Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }. // by parsing the function with PreParser. Consumes the ending }.
void SkipLazyFunctionBody(Handle<String> function_name, void SkipLazyFunctionBody(const AstRawString* function_name,
int* materialized_literal_count, int* materialized_literal_count,
int* expected_property_count, int* expected_property_count,
bool* ok); bool* ok);
@ -780,12 +793,9 @@ class Parser : public ParserBase<ParserTraits> {
SingletonLogger* logger); SingletonLogger* logger);
// Consumes the ending }. // Consumes the ending }.
ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name, ZoneList<Statement*>* ParseEagerFunctionBody(
int pos, const AstRawString* function_name, int pos, Variable* fvar,
Variable* fvar, Token::Value fvar_init_op, bool is_generator, bool* ok);
Token::Value fvar_init_op,
bool is_generator,
bool* ok);
void ThrowPendingError(); void ThrowPendingError();
@ -798,6 +808,7 @@ class Parser : public ParserBase<ParserTraits> {
Target* target_stack_; // for break, continue statements Target* target_stack_; // for break, continue statements
ScriptData** cached_data_; ScriptData** cached_data_;
CachedDataMode cached_data_mode_; CachedDataMode cached_data_mode_;
AstValueFactory* ast_value_factory_;
CompilationInfo* info_; CompilationInfo* info_;
@ -805,7 +816,7 @@ class Parser : public ParserBase<ParserTraits> {
bool has_pending_error_; bool has_pending_error_;
Scanner::Location pending_error_location_; Scanner::Location pending_error_location_;
const char* pending_error_message_; const char* pending_error_message_;
MaybeHandle<String> pending_error_arg_; const AstRawString* pending_error_arg_;
const char* pending_error_char_arg_; const char* pending_error_char_arg_;
bool pending_error_is_reference_error_; bool pending_error_is_reference_error_;
}; };

View File

@ -150,7 +150,8 @@ class ParserBase : public Traits {
FunctionState** function_state_stack, FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack, typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope, typename Traits::Type::Scope* scope,
typename Traits::Type::Zone* zone = NULL); typename Traits::Type::Zone* zone = NULL,
AstValueFactory* ast_value_factory = NULL);
~FunctionState(); ~FunctionState();
int NextMaterializedLiteralIndex() { int NextMaterializedLiteralIndex() {
@ -395,7 +396,9 @@ class ParserBase : public Traits {
void ReportMessageAt(Scanner::Location location, const char* message, void ReportMessageAt(Scanner::Location location, const char* message,
bool is_reference_error = false) { 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); void ReportUnexpectedToken(Token::Value token);
@ -782,9 +785,9 @@ class PreParserScope {
class PreParserFactory { class PreParserFactory {
public: public:
explicit PreParserFactory(void* extra_param) {} explicit PreParserFactory(void* extra_param1, void* extra_param2) {}
PreParserExpression NewLiteral(PreParserIdentifier identifier, PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
int pos) { int pos) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
PreParserExpression NewNumberLiteral(double number, PreParserExpression NewNumberLiteral(double number,
@ -1036,8 +1039,8 @@ class PreParserTraits {
// Producing data during the recursive descent. // Producing data during the recursive descent.
PreParserIdentifier GetSymbol(Scanner* scanner); PreParserIdentifier GetSymbol(Scanner* scanner);
static PreParserIdentifier NextLiteralString(Scanner* scanner,
PretenureFlag tenured) { static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
return PreParserIdentifier::Default(); return PreParserIdentifier::Default();
} }
@ -1225,7 +1228,8 @@ ParserBase<Traits>::FunctionState::FunctionState(
FunctionState** function_state_stack, FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack, typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope, 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_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
next_handler_index_(0), next_handler_index_(0),
expected_property_count_(0), expected_property_count_(0),
@ -1237,7 +1241,7 @@ ParserBase<Traits>::FunctionState::FunctionState(
outer_scope_(*scope_stack), outer_scope_(*scope_stack),
saved_ast_node_id_(0), saved_ast_node_id_(0),
extra_param_(extra_param), extra_param_(extra_param),
factory_(extra_param) { factory_(extra_param, ast_value_factory) {
*scope_stack_ = scope; *scope_stack_ = scope;
*function_state_stack = this; *function_state_stack = this;
Traits::SetUpFunctionState(this, extra_param); Traits::SetUpFunctionState(this, extra_param);
@ -1363,14 +1367,14 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
int literal_index = function_state_->NextMaterializedLiteralIndex(); int literal_index = function_state_->NextMaterializedLiteralIndex();
IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED); IdentifierT js_pattern = this->GetNextSymbol(scanner());
if (!scanner()->ScanRegExpFlags()) { if (!scanner()->ScanRegExpFlags()) {
Next(); Next();
ReportMessage("invalid_regexp_flags"); ReportMessage("invalid_regexp_flags");
*ok = false; *ok = false;
return Traits::EmptyExpression(); return Traits::EmptyExpression();
} }
IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED); IdentifierT js_flags = this->GetNextSymbol(scanner());
Next(); Next();
return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
} }
@ -1615,7 +1619,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
} }
// Failed to parse as get/set property, so it's just a normal property // Failed to parse as get/set property, so it's just a normal property
// (which might be called "get" or "set" or something else). // (which might be called "get" or "set" or something else).
key = factory()->NewLiteral(id, next_pos); key = factory()->NewStringLiteral(id, next_pos);
break; break;
} }
case Token::STRING: { case Token::STRING: {
@ -1627,7 +1631,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
key = factory()->NewNumberLiteral(index, next_pos); key = factory()->NewNumberLiteral(index, next_pos);
break; break;
} }
key = factory()->NewLiteral(string, next_pos); key = factory()->NewStringLiteral(string, next_pos);
break; break;
} }
case Token::NUMBER: { case Token::NUMBER: {
@ -1640,7 +1644,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
if (Token::IsKeyword(next)) { if (Token::IsKeyword(next)) {
Consume(next); Consume(next);
IdentifierT string = this->GetSymbol(scanner_); IdentifierT string = this->GetSymbol(scanner_);
key = factory()->NewLiteral(string, next_pos); key = factory()->NewStringLiteral(string, next_pos);
} else { } else {
Token::Value next = Next(); Token::Value next = Next();
ReportUnexpectedToken(next); ReportUnexpectedToken(next);
@ -2009,7 +2013,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
int pos = position(); int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK); IdentifierT name = ParseIdentifierName(CHECK_OK);
result = factory()->NewProperty( result = factory()->NewProperty(
result, factory()->NewLiteral(name, pos), pos); result, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) this->PushLiteralName(fni_, name); if (fni_ != NULL) this->PushLiteralName(fni_, name);
break; break;
} }
@ -2132,7 +2136,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
int pos = position(); int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK); IdentifierT name = ParseIdentifierName(CHECK_OK);
expression = factory()->NewProperty( expression = factory()->NewProperty(
expression, factory()->NewLiteral(name, pos), pos); expression, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) { if (fni_ != NULL) {
this->PushLiteralName(fni_, name); this->PushLiteralName(fni_, name);
} }

View File

@ -6,6 +6,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/ast-value-factory.h"
#include "src/platform.h" #include "src/platform.h"
#include "src/prettyprinter.h" #include "src/prettyprinter.h"
#include "src/scopes.h" #include "src/scopes.h"
@ -133,7 +134,7 @@ void PrettyPrinter::VisitIfStatement(IfStatement* node) {
void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) { void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
Print("continue"); Print("continue");
ZoneStringList* labels = node->target()->labels(); ZoneList<const AstRawString*>* labels = node->target()->labels();
if (labels != NULL) { if (labels != NULL) {
Print(" "); Print(" ");
ASSERT(labels->length() > 0); // guaranteed to have at least one entry ASSERT(labels->length() > 0); // guaranteed to have at least one entry
@ -145,7 +146,7 @@ void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
void PrettyPrinter::VisitBreakStatement(BreakStatement* node) { void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
Print("break"); Print("break");
ZoneStringList* labels = node->target()->labels(); ZoneList<const AstRawString*>* labels = node->target()->labels();
if (labels != NULL) { if (labels != NULL) {
Print(" "); Print(" ");
ASSERT(labels->length() > 0); // guaranteed to have at least one entry ASSERT(labels->length() > 0); // guaranteed to have at least one entry
@ -524,7 +525,7 @@ void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
} }
void PrettyPrinter::PrintLabels(ZoneStringList* labels) { void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
if (labels != NULL) { if (labels != NULL) {
for (int i = 0; i < labels->length(); i++) { for (int i = 0; i < labels->length(); i++) {
PrintLiteral(labels->at(i), false); PrintLiteral(labels->at(i), false);
@ -582,6 +583,11 @@ void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
} }
void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
PrintLiteral(value->string(), quote);
}
void PrettyPrinter::PrintParameters(Scope* scope) { void PrettyPrinter::PrintParameters(Scope* scope) {
Print("("); Print("(");
for (int i = 0; i < scope->num_parameters(); i++) { for (int i = 0; i < scope->num_parameters(); i++) {
@ -676,7 +682,7 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info,
} }
void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) { void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
if (labels == NULL || labels->length() == 0) return; if (labels == NULL || labels->length() == 0) return;
PrintIndented("LABELS "); PrintIndented("LABELS ");
PrintLabels(labels); PrintLabels(labels);

View File

@ -44,9 +44,10 @@ class PrettyPrinter: public AstVisitor {
const char* Output() const { return output_; } const char* Output() const { return output_; }
virtual void PrintStatements(ZoneList<Statement*>* statements); virtual void PrintStatements(ZoneList<Statement*>* statements);
void PrintLabels(ZoneStringList* labels); void PrintLabels(ZoneList<const AstRawString*>* labels);
virtual void PrintArguments(ZoneList<Expression*>* arguments); virtual void PrintArguments(ZoneList<Expression*>* arguments);
void PrintLiteral(Handle<Object> value, bool quote); void PrintLiteral(Handle<Object> value, bool quote);
void PrintLiteral(const AstRawString* value, bool quote);
void PrintParameters(Scope* scope); void PrintParameters(Scope* scope);
void PrintDeclarations(ZoneList<Declaration*>* declarations); void PrintDeclarations(ZoneList<Declaration*>* declarations);
void PrintFunctionLiteral(FunctionLiteral* function); void PrintFunctionLiteral(FunctionLiteral* function);
@ -83,7 +84,7 @@ class AstPrinter: public PrettyPrinter {
void PrintLiteralWithModeIndented(const char* info, void PrintLiteralWithModeIndented(const char* info,
Variable* var, Variable* var,
Handle<Object> value); Handle<Object> value);
void PrintLabelsIndented(ZoneStringList* labels); void PrintLabelsIndented(ZoneList<const AstRawString*>* labels);
void inc_indent() { indent_++; } void inc_indent() { indent_++; }
void dec_indent() { indent_--; } void dec_indent() { indent_--; }

View File

@ -20,7 +20,9 @@ class Processor: public AstVisitor {
result_assigned_(false), result_assigned_(false),
is_set_(false), is_set_(false),
in_try_(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); InitializeAstVisitor(zone);
} }
@ -234,8 +236,10 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
ZoneList<Statement*>* body = function->body(); ZoneList<Statement*>* body = function->body();
if (!body->is_empty()) { if (!body->is_empty()) {
Variable* result = scope->NewTemporary( Variable* result =
info->isolate()->factory()->dot_result_string()); 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 processor(result, info->zone());
processor.Process(body); processor.Process(body);
if (processor.HasStackOverflow()) return false; if (processor.HasStackOverflow()) return false;
@ -250,7 +254,7 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
// coincides with the end of the with scope which is the position of '1'. // coincides with the end of the with scope which is the position of '1'.
int pos = function->end_position(); int pos = function->end_position();
VariableProxy* result_proxy = processor.factory()->NewVariableProxy( VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
result->name(), false, result->interface(), pos); result->raw_name(), false, result->interface(), pos);
result_proxy->BindTo(result); result_proxy->BindTo(result);
Statement* result_statement = Statement* result_statement =
processor.factory()->NewReturnStatement(result_proxy, pos); processor.factory()->NewReturnStatement(result_proxy, pos);

View File

@ -9,6 +9,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "include/v8stdint.h" #include "include/v8stdint.h"
#include "src/ast-value-factory.h"
#include "src/char-predicates-inl.h" #include "src/char-predicates-inl.h"
#include "src/conversions-inl.h" #include "src/conversions-inl.h"
#include "src/list-inl.h" #include "src/list-inl.h"
@ -1093,26 +1094,19 @@ bool Scanner::ScanRegExpFlags() {
} }
Handle<String> Scanner::AllocateNextLiteralString(Isolate* isolate, const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) {
PretenureFlag tenured) { if (is_literal_one_byte()) {
if (is_next_literal_one_byte()) { return ast_value_factory->GetOneByteString(literal_one_byte_string());
return isolate->factory()->NewStringFromOneByte(
next_literal_one_byte_string(), tenured).ToHandleChecked();
} else {
return isolate->factory()->NewStringFromTwoByte(
next_literal_two_byte_string(), tenured).ToHandleChecked();
} }
return ast_value_factory->GetTwoByteString(literal_two_byte_string());
} }
Handle<String> Scanner::AllocateInternalizedString(Isolate* isolate) { const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) {
if (is_literal_one_byte()) { if (is_next_literal_one_byte()) {
return isolate->factory()->InternalizeOneByteString( return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
literal_one_byte_string());
} else {
return isolate->factory()->InternalizeTwoByteString(
literal_two_byte_string());
} }
return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
} }

View File

@ -21,6 +21,8 @@ namespace v8 {
namespace internal { namespace internal {
class AstRawString;
class AstValueFactory;
class ParserRecorder; class ParserRecorder;
@ -376,9 +378,8 @@ class Scanner {
return next_.literal_chars->is_contextual_keyword(keyword); return next_.literal_chars->is_contextual_keyword(keyword);
} }
Handle<String> AllocateNextLiteralString(Isolate* isolate, const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
PretenureFlag tenured); const AstRawString* NextSymbol(AstValueFactory* ast_value_factory);
Handle<String> AllocateInternalizedString(Isolate* isolate);
double DoubleValue(); double DoubleValue();
bool UnescapedLiteralMatches(const char* data, int length) { bool UnescapedLiteralMatches(const char* data, int length) {

View File

@ -540,7 +540,7 @@ Handle<ModuleInfo> ModuleInfo::Create(
for (Interface::Iterator it = interface->iterator(); for (Interface::Iterator it = interface->iterator();
!it.done(); it.Advance(), ++i) { !it.done(); it.Advance(), ++i) {
Variable* var = scope->LookupLocal(it.name()); 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()); info->set_mode(i, var->mode());
ASSERT((var->mode() == MODULE) == (it.interface()->IsModule())); ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
if (var->mode() == MODULE) { if (var->mode() == MODULE) {

View File

@ -24,34 +24,28 @@ namespace internal {
// use. Because a Variable holding a handle with the same location exists // use. Because a Variable holding a handle with the same location exists
// this is ensured. // 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) VariableMap::VariableMap(Zone* zone)
: ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)), : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
zone_(zone) {} zone_(zone) {}
VariableMap::~VariableMap() {} VariableMap::~VariableMap() {}
Variable* VariableMap::Declare( Variable* VariableMap::Declare(
Scope* scope, Scope* scope,
Handle<String> name, const AstRawString* name,
VariableMode mode, VariableMode mode,
bool is_valid_lhs, bool is_valid_lhs,
Variable::Kind kind, Variable::Kind kind,
InitializationFlag initialization_flag, InitializationFlag initialization_flag,
Interface* interface) { Interface* interface) {
Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true, // AstRawStrings are unambiguous, i.e., the same string is always represented
ZoneAllocationPolicy(zone())); // by the same AstRawString*.
// FIXME(marja): fix the type of Lookup.
Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
true, ZoneAllocationPolicy(zone()));
if (p->value == NULL) { if (p->value == NULL) {
// The variable has not been declared yet -> insert it. // The variable has not been declared yet -> insert it.
ASSERT(p->key == name.location()); ASSERT(p->key == name);
p->value = new(zone()) Variable(scope, p->value = new(zone()) Variable(scope,
name, name,
mode, mode,
@ -64,11 +58,11 @@ Variable* VariableMap::Declare(
} }
Variable* VariableMap::Lookup(Handle<String> name) { Variable* VariableMap::Lookup(const AstRawString* name) {
Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false, Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
ZoneAllocationPolicy(NULL)); false, ZoneAllocationPolicy(NULL));
if (p != NULL) { if (p != NULL) {
ASSERT(*reinterpret_cast<String**>(p->key) == *name); ASSERT(reinterpret_cast<const AstRawString*>(p->key) == name);
ASSERT(p->value != NULL); ASSERT(p->value != NULL);
return reinterpret_cast<Variable*>(p->value); return reinterpret_cast<Variable*>(p->value);
} }
@ -79,7 +73,8 @@ Variable* VariableMap::Lookup(Handle<String> name) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Implementation of Scope // 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()), : isolate_(zone->isolate()),
inner_scopes_(4, zone), inner_scopes_(4, zone),
variables_(zone), variables_(zone),
@ -92,6 +87,7 @@ Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
(scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE) (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
? Interface::NewModule(zone) : NULL), ? Interface::NewModule(zone) : NULL),
already_resolved_(false), already_resolved_(false),
ast_value_factory_(ast_value_factory),
zone_(zone) { zone_(zone) {
SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
// The outermost scope must be a global scope. // The outermost scope must be a global scope.
@ -103,6 +99,7 @@ Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
Scope::Scope(Scope* inner_scope, Scope::Scope(Scope* inner_scope,
ScopeType scope_type, ScopeType scope_type,
Handle<ScopeInfo> scope_info, Handle<ScopeInfo> scope_info,
AstValueFactory* value_factory,
Zone* zone) Zone* zone)
: isolate_(zone->isolate()), : isolate_(zone->isolate()),
inner_scopes_(4, zone), inner_scopes_(4, zone),
@ -114,6 +111,7 @@ Scope::Scope(Scope* inner_scope,
decls_(4, zone), decls_(4, zone),
interface_(NULL), interface_(NULL),
already_resolved_(true), already_resolved_(true),
ast_value_factory_(value_factory),
zone_(zone) { zone_(zone) {
SetDefaults(scope_type, NULL, scope_info); SetDefaults(scope_type, NULL, scope_info);
if (!scope_info.is_null()) { if (!scope_info.is_null()) {
@ -126,7 +124,8 @@ Scope::Scope(Scope* inner_scope,
} }
Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone) Scope::Scope(Scope* inner_scope, const AstRawString* catch_variable_name,
AstValueFactory* value_factory, Zone* zone)
: isolate_(zone->isolate()), : isolate_(zone->isolate()),
inner_scopes_(1, zone), inner_scopes_(1, zone),
variables_(zone), variables_(zone),
@ -137,6 +136,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
decls_(0, zone), decls_(0, zone),
interface_(NULL), interface_(NULL),
already_resolved_(true), already_resolved_(true),
ast_value_factory_(value_factory),
zone_(zone) { zone_(zone) {
SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
AddInnerScope(inner_scope); AddInnerScope(inner_scope);
@ -157,7 +157,7 @@ void Scope::SetDefaults(ScopeType scope_type,
Handle<ScopeInfo> scope_info) { Handle<ScopeInfo> scope_info) {
outer_scope_ = outer_scope; outer_scope_ = outer_scope;
scope_type_ = scope_type; scope_type_ = scope_type;
scope_name_ = isolate_->factory()->empty_string(); scope_name_ = ast_value_factory_->empty_string();
dynamics_ = NULL; dynamics_ = NULL;
receiver_ = NULL; receiver_ = NULL;
function_ = NULL; function_ = NULL;
@ -199,6 +199,7 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
Scope* with_scope = new(zone) Scope(current_scope, Scope* with_scope = new(zone) Scope(current_scope,
WITH_SCOPE, WITH_SCOPE,
Handle<ScopeInfo>::null(), Handle<ScopeInfo>::null(),
global_scope->ast_value_factory_,
zone); zone);
current_scope = with_scope; current_scope = with_scope;
// All the inner scopes are inside a with. // All the inner scopes are inside a with.
@ -211,30 +212,36 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
current_scope = new(zone) Scope(current_scope, current_scope = new(zone) Scope(current_scope,
GLOBAL_SCOPE, GLOBAL_SCOPE,
Handle<ScopeInfo>(scope_info), Handle<ScopeInfo>(scope_info),
global_scope->ast_value_factory_,
zone); zone);
} else if (context->IsModuleContext()) { } else if (context->IsModuleContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
current_scope = new(zone) Scope(current_scope, current_scope = new(zone) Scope(current_scope,
MODULE_SCOPE, MODULE_SCOPE,
Handle<ScopeInfo>(scope_info), Handle<ScopeInfo>(scope_info),
global_scope->ast_value_factory_,
zone); zone);
} else if (context->IsFunctionContext()) { } else if (context->IsFunctionContext()) {
ScopeInfo* scope_info = context->closure()->shared()->scope_info(); ScopeInfo* scope_info = context->closure()->shared()->scope_info();
current_scope = new(zone) Scope(current_scope, current_scope = new(zone) Scope(current_scope,
FUNCTION_SCOPE, FUNCTION_SCOPE,
Handle<ScopeInfo>(scope_info), Handle<ScopeInfo>(scope_info),
global_scope->ast_value_factory_,
zone); zone);
} else if (context->IsBlockContext()) { } else if (context->IsBlockContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
current_scope = new(zone) Scope(current_scope, current_scope = new(zone) Scope(current_scope,
BLOCK_SCOPE, BLOCK_SCOPE,
Handle<ScopeInfo>(scope_info), Handle<ScopeInfo>(scope_info),
global_scope->ast_value_factory_,
zone); zone);
} else { } else {
ASSERT(context->IsCatchContext()); ASSERT(context->IsCatchContext());
String* name = String::cast(context->extension()); String* name = String::cast(context->extension());
current_scope = new(zone) Scope( current_scope = new (zone) Scope(
current_scope, Handle<String>(name), zone); current_scope,
global_scope->ast_value_factory_->GetString(Handle<String>(name)),
global_scope->ast_value_factory_, zone);
} }
if (contains_with) current_scope->RecordWithStatement(); if (contains_with) current_scope->RecordWithStatement();
if (innermost_scope == NULL) innermost_scope = current_scope; if (innermost_scope == NULL) innermost_scope = current_scope;
@ -266,7 +273,9 @@ bool Scope::Analyze(CompilationInfo* info) {
// Allocate the variables. // 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 (!top->AllocateVariables(info, &ast_node_factory)) return false;
} }
@ -310,7 +319,7 @@ void Scope::Initialize() {
if (is_declaration_scope()) { if (is_declaration_scope()) {
Variable* var = Variable* var =
variables_.Declare(this, variables_.Declare(this,
isolate_->factory()->this_string(), ast_value_factory_->this_string(),
VAR, VAR,
false, false,
Variable::THIS, Variable::THIS,
@ -327,7 +336,7 @@ void Scope::Initialize() {
// Note that it might never be accessed, in which case it won't be // Note that it might never be accessed, in which case it won't be
// allocated during variable allocation. // allocated during variable allocation.
variables_.Declare(this, variables_.Declare(this,
isolate_->factory()->arguments_string(), ast_value_factory_->arguments_string(),
VAR, VAR,
true, true,
Variable::ARGUMENTS, Variable::ARGUMENTS,
@ -366,23 +375,28 @@ Scope* Scope::FinalizeBlockScope() {
} }
Variable* Scope::LookupLocal(Handle<String> name) { Variable* Scope::LookupLocal(const AstRawString* name) {
Variable* result = variables_.Lookup(name); Variable* result = variables_.Lookup(name);
if (result != NULL || scope_info_.is_null()) { if (result != NULL || scope_info_.is_null()) {
return result; 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. // If we have a serialized scope info, we might find the variable there.
// There should be no local slot with the given name. // 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. // Check context slot lookup.
VariableMode mode; VariableMode mode;
Variable::Location location = Variable::CONTEXT; Variable::Location location = Variable::CONTEXT;
InitializationFlag init_flag; 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) { if (index < 0) {
// Check parameters. // Check parameters.
index = scope_info_->ParameterIndex(*name); index = scope_info_->ParameterIndex(*name_handle);
if (index < 0) return NULL; if (index < 0) return NULL;
mode = DYNAMIC; mode = DYNAMIC;
@ -397,14 +411,14 @@ Variable* Scope::LookupLocal(Handle<String> name) {
} }
Variable* Scope::LookupFunctionVar(Handle<String> name, Variable* Scope::LookupFunctionVar(const AstRawString* name,
AstNodeFactory<AstNullVisitor>* factory) { 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(); return function_->proxy()->var();
} else if (!scope_info_.is_null()) { } else if (!scope_info_.is_null()) {
// If we are backed by a scope info, try to lookup the variable there. // If we are backed by a scope info, try to lookup the variable there.
VariableMode mode; VariableMode mode;
int index = scope_info_->FunctionContextSlotIndex(*name, &mode); int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
if (index < 0) return NULL; if (index < 0) return NULL;
Variable* var = new(zone()) Variable( Variable* var = new(zone()) Variable(
this, name, mode, true /* is valid LHS */, this, name, mode, true /* is valid LHS */,
@ -421,7 +435,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name,
} }
Variable* Scope::Lookup(Handle<String> name) { Variable* Scope::Lookup(const AstRawString* name) {
for (Scope* scope = this; for (Scope* scope = this;
scope != NULL; scope != NULL;
scope = scope->outer_scope()) { scope = scope->outer_scope()) {
@ -432,7 +446,7 @@ Variable* Scope::Lookup(Handle<String> name) {
} }
void Scope::DeclareParameter(Handle<String> name, VariableMode mode) { void Scope::DeclareParameter(const AstRawString* name, VariableMode mode) {
ASSERT(!already_resolved()); ASSERT(!already_resolved());
ASSERT(is_function_scope()); ASSERT(is_function_scope());
Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
@ -441,7 +455,7 @@ void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
} }
Variable* Scope::DeclareLocal(Handle<String> name, Variable* Scope::DeclareLocal(const AstRawString* name,
VariableMode mode, VariableMode mode,
InitializationFlag init_flag, InitializationFlag init_flag,
Interface* interface) { Interface* interface) {
@ -456,7 +470,7 @@ Variable* Scope::DeclareLocal(Handle<String> name,
} }
Variable* Scope::DeclareDynamicGlobal(Handle<String> name) { Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) {
ASSERT(is_global_scope()); ASSERT(is_global_scope());
return variables_.Declare(this, return variables_.Declare(this,
name, name,
@ -479,7 +493,7 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
} }
Variable* Scope::NewInternal(Handle<String> name) { Variable* Scope::NewInternal(const AstRawString* name) {
ASSERT(!already_resolved()); ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this, Variable* var = new(zone()) Variable(this,
name, name,
@ -492,7 +506,7 @@ Variable* Scope::NewInternal(Handle<String> name) {
} }
Variable* Scope::NewTemporary(Handle<String> name) { Variable* Scope::NewTemporary(const AstRawString* name) {
ASSERT(!already_resolved()); ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this, Variable* var = new(zone()) Variable(this,
name, name,
@ -530,7 +544,7 @@ Declaration* Scope::CheckConflictingVarDeclarations() {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
Declaration* decl = decls_[i]; Declaration* decl = decls_[i];
if (decl->mode() != VAR) continue; if (decl->mode() != VAR) continue;
Handle<String> name = decl->proxy()->name(); const AstRawString* name = decl->proxy()->raw_name();
// Iterate through all scopes until and including the declaration scope. // Iterate through all scopes until and including the declaration scope.
Scope* previous = NULL; Scope* previous = NULL;
@ -773,9 +787,8 @@ static void Indent(int n, const char* str) {
} }
static void PrintName(Handle<String> name) { static void PrintName(const AstRawString* name) {
SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS); PrintF("%.*s", name->length(), name->raw_data());
PrintF("%s", s.get());
} }
@ -803,7 +816,7 @@ static void PrintVar(int indent, Variable* var) {
if (var->is_used() || !var->IsUnallocated()) { if (var->is_used() || !var->IsUnallocated()) {
Indent(indent, Variable::Mode2String(var->mode())); Indent(indent, Variable::Mode2String(var->mode()));
PrintF(" "); PrintF(" ");
PrintName(var->name()); PrintName(var->raw_name());
PrintF("; // "); PrintF("; // ");
PrintLocation(var); PrintLocation(var);
if (var->has_forced_context_allocation()) { if (var->has_forced_context_allocation()) {
@ -829,7 +842,7 @@ void Scope::Print(int n) {
// Print header. // Print header.
Indent(n0, Header(scope_type_)); Indent(n0, Header(scope_type_));
if (scope_name_->length() > 0) { if (!scope_name_->IsEmpty()) {
PrintF(" "); PrintF(" ");
PrintName(scope_name_); PrintName(scope_name_);
} }
@ -839,7 +852,7 @@ void Scope::Print(int n) {
PrintF(" ("); PrintF(" (");
for (int i = 0; i < params_.length(); i++) { for (int i = 0; i < params_.length(); i++) {
if (i > 0) PrintF(", "); if (i > 0) PrintF(", ");
PrintName(params_[i]->name()); PrintName(params_[i]->raw_name());
} }
PrintF(")"); PrintF(")");
} }
@ -849,7 +862,7 @@ void Scope::Print(int n) {
// Function name, if any (named function literals, only). // Function name, if any (named function literals, only).
if (function_ != NULL) { if (function_ != NULL) {
Indent(n1, "// (local) function name: "); Indent(n1, "// (local) function name: ");
PrintName(function_->proxy()->name()); PrintName(function_->proxy()->raw_name());
PrintF("\n"); PrintF("\n");
} }
@ -917,8 +930,8 @@ void Scope::Print(int n) {
#endif // DEBUG #endif // DEBUG
Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) { Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone()); if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
VariableMap* map = dynamics_->GetMap(mode); VariableMap* map = dynamics_->GetMap(mode);
Variable* var = map->Lookup(name); Variable* var = map->Lookup(name);
if (var == NULL) { if (var == NULL) {
@ -938,7 +951,7 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
} }
Variable* Scope::LookupRecursive(Handle<String> name, Variable* Scope::LookupRecursive(const AstRawString* name,
BindingKind* binding_kind, BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory) { AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL); ASSERT(binding_kind != NULL);
@ -1012,7 +1025,7 @@ bool Scope::ResolveVariable(CompilationInfo* info,
// Otherwise, try to resolve the variable. // Otherwise, try to resolve the variable.
BindingKind binding_kind; BindingKind binding_kind;
Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory); Variable* var = LookupRecursive(proxy->raw_name(), &binding_kind, factory);
switch (binding_kind) { switch (binding_kind) {
case BOUND: case BOUND:
// We found a variable binding. // We found a variable binding.
@ -1024,29 +1037,29 @@ bool Scope::ResolveVariable(CompilationInfo* info,
// scope which was not promoted to a context, this can happen if we use // scope which was not promoted to a context, this can happen if we use
// debugger to evaluate arbitrary expressions at a break point). // debugger to evaluate arbitrary expressions at a break point).
if (var->IsGlobalObjectProperty()) { if (var->IsGlobalObjectProperty()) {
var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
} else if (var->is_dynamic()) { } else if (var->is_dynamic()) {
var = NonLocal(proxy->name(), DYNAMIC); var = NonLocal(proxy->raw_name(), DYNAMIC);
} else { } else {
Variable* invalidated = var; Variable* invalidated = var;
var = NonLocal(proxy->name(), DYNAMIC_LOCAL); var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
var->set_local_if_not_shadowed(invalidated); var->set_local_if_not_shadowed(invalidated);
} }
break; break;
case UNBOUND: case UNBOUND:
// No binding has been found. Declare a variable on the global object. // 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; break;
case UNBOUND_EVAL_SHADOWED: case UNBOUND_EVAL_SHADOWED:
// No binding has been found. But some scope makes a sloppy 'eval' call. // 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; break;
case DYNAMIC_LOOKUP: case DYNAMIC_LOOKUP:
// The variable could not be resolved statically. // The variable could not be resolved statically.
var = NonLocal(proxy->name(), DYNAMIC); var = NonLocal(proxy->raw_name(), DYNAMIC);
break; break;
} }
@ -1069,8 +1082,10 @@ bool Scope::ResolveVariable(CompilationInfo* info,
if (FLAG_harmony_modules) { if (FLAG_harmony_modules) {
bool ok; bool ok;
#ifdef DEBUG #ifdef DEBUG
if (FLAG_print_interface_details) if (FLAG_print_interface_details) {
PrintF("# Resolve %s:\n", var->name()->ToAsciiArray()); PrintF("# Resolve %.*s:\n", var->raw_name()->length(),
var->raw_name()->raw_data());
}
#endif #endif
proxy->interface()->Unify(var->interface(), zone(), &ok); proxy->interface()->Unify(var->interface(), zone(), &ok);
if (!ok) { if (!ok) {
@ -1150,7 +1165,7 @@ bool Scope::MustAllocate(Variable* var) {
// Give var a read/write use if there is a chance it might be accessed // 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 // via an eval() call. This is only possible if the variable has a
// visible name. // visible name.
if ((var->is_this() || var->name()->length() > 0) && if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
(var->has_forced_context_allocation() || (var->has_forced_context_allocation() ||
scope_calls_eval_ || scope_calls_eval_ ||
inner_scope_calls_eval_ || inner_scope_calls_eval_ ||
@ -1211,7 +1226,7 @@ void Scope::AllocateHeapSlot(Variable* var) {
void Scope::AllocateParameterLocals() { void Scope::AllocateParameterLocals() {
ASSERT(is_function_scope()); 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 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
bool uses_sloppy_arguments = false; bool uses_sloppy_arguments = false;
@ -1352,10 +1367,9 @@ void Scope::AllocateModulesRecursively(Scope* host_scope) {
if (already_resolved()) return; if (already_resolved()) return;
if (is_module_scope()) { if (is_module_scope()) {
ASSERT(interface_->IsFrozen()); ASSERT(interface_->IsFrozen());
Handle<String> name = isolate_->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR(".module"));
ASSERT(module_var_ == NULL); 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_; ++host_scope->num_modules_;
} }

View File

@ -22,14 +22,14 @@ class VariableMap: public ZoneHashMap {
virtual ~VariableMap(); virtual ~VariableMap();
Variable* Declare(Scope* scope, Variable* Declare(Scope* scope,
Handle<String> name, const AstRawString* name,
VariableMode mode, VariableMode mode,
bool is_valid_lhs, bool is_valid_lhs,
Variable::Kind kind, Variable::Kind kind,
InitializationFlag initialization_flag, InitializationFlag initialization_flag,
Interface* interface = Interface::NewValue()); Interface* interface = Interface::NewValue());
Variable* Lookup(Handle<String> name); Variable* Lookup(const AstRawString* name);
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
@ -74,7 +74,8 @@ class Scope: public ZoneObject {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Construction // 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 // Compute top scope and allocate variables. For lazy compilation the top
// scope only contains the single lazily compiled function, so this // scope only contains the single lazily compiled function, so this
@ -85,7 +86,9 @@ class Scope: public ZoneObject {
Zone* zone); Zone* zone);
// The scope name is only used for printing/debugging. // The scope name is only used for printing/debugging.
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } void SetScopeName(const AstRawString* scope_name) {
scope_name_ = scope_name;
}
void Initialize(); void Initialize();
@ -100,18 +103,18 @@ class Scope: public ZoneObject {
// Declarations // Declarations
// Lookup a variable in this scope. Returns the variable or NULL if not found. // Lookup a variable in this scope. Returns the variable or NULL if not found.
Variable* LookupLocal(Handle<String> name); Variable* LookupLocal(const AstRawString* name);
// This lookup corresponds to a lookup in the "intermediate" scope sitting // This lookup corresponds to a lookup in the "intermediate" scope sitting
// between this scope and the outer scope. (ECMA-262, 3rd., requires that // between this scope and the outer scope. (ECMA-262, 3rd., requires that
// the name of named function literal is kept in an intermediate scope // the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.) // in between this scope and the next outer scope.)
Variable* LookupFunctionVar(Handle<String> name, Variable* LookupFunctionVar(const AstRawString* name,
AstNodeFactory<AstNullVisitor>* factory); AstNodeFactory<AstNullVisitor>* factory);
// Lookup a variable in this scope or outer scopes. // Lookup a variable in this scope or outer scopes.
// Returns the variable or NULL if not found. // Returns the variable or NULL if not found.
Variable* Lookup(Handle<String> name); Variable* Lookup(const AstRawString* name);
// Declare the function variable for a function literal. This variable // Declare the function variable for a function literal. This variable
// is in an intermediate scope between this function scope and the the // is in an intermediate scope between this function scope and the the
@ -124,11 +127,11 @@ class Scope: public ZoneObject {
// Declare a parameter in this scope. When there are duplicated // Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation // parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right. // expects all parameters to be declared and from left to right.
void DeclareParameter(Handle<String> name, VariableMode mode); void DeclareParameter(const AstRawString* name, VariableMode mode);
// Declare a local variable in this scope. If the variable has been // Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned. // declared before, the previously declared variable is returned.
Variable* DeclareLocal(Handle<String> name, Variable* DeclareLocal(const AstRawString* name,
VariableMode mode, VariableMode mode,
InitializationFlag init_flag, InitializationFlag init_flag,
Interface* interface = Interface::NewValue()); Interface* interface = Interface::NewValue());
@ -137,12 +140,12 @@ class Scope: public ZoneObject {
// global scope. The variable was introduced (possibly from an inner // global scope. The variable was introduced (possibly from an inner
// scope) by a reference to an unresolved variable with no intervening // scope) by a reference to an unresolved variable with no intervening
// with statements or eval calls. // with statements or eval calls.
Variable* DeclareDynamicGlobal(Handle<String> name); Variable* DeclareDynamicGlobal(const AstRawString* name);
// Create a new unresolved variable. // Create a new unresolved variable.
template<class Visitor> template<class Visitor>
VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory, VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
Handle<String> name, const AstRawString* name,
Interface* interface = Interface::NewValue(), Interface* interface = Interface::NewValue(),
int position = RelocInfo::kNoPosition) { int position = RelocInfo::kNoPosition) {
// Note that we must not share the unresolved variables with // Note that we must not share the unresolved variables with
@ -167,13 +170,13 @@ class Scope: public ZoneObject {
// for printing and cannot be used to find the variable. In particular, // 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* // the only way to get hold of the temporary is by keeping the Variable*
// around. // around.
Variable* NewInternal(Handle<String> name); Variable* NewInternal(const AstRawString* name);
// Creates a new temporary variable in this scope. The name is only used // 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, // 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* // 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. // around. The name should not clash with a legitimate variable names.
Variable* NewTemporary(Handle<String> name); Variable* NewTemporary(const AstRawString* name);
// Adds the specific declaration node to the list of declarations in // Adds the specific declaration node to the list of declarations in
// this scope. The declarations are processed as part of entering // this scope. The declarations are processed as part of entering
@ -390,7 +393,7 @@ class Scope: public ZoneObject {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Strict mode support. // Strict mode support.
bool IsDeclared(Handle<String> name) { bool IsDeclared(const AstRawString* name) {
// During formal parameter list parsing the scope only contains // During formal parameter list parsing the scope only contains
// two variables inserted at initialization: "this" and "arguments". // two variables inserted at initialization: "this" and "arguments".
// "this" is an invalid parameter name and "arguments" is invalid parameter // "this" is an invalid parameter name and "arguments" is invalid parameter
@ -421,7 +424,7 @@ class Scope: public ZoneObject {
ScopeType scope_type_; ScopeType scope_type_;
// Debugging support. // Debugging support.
Handle<String> scope_name_; const AstRawString* scope_name_;
// The variables declared in this scope: // The variables declared in this scope:
// //
@ -497,7 +500,7 @@ class Scope: public ZoneObject {
// Create a non-local variable with a given name. // Create a non-local variable with a given name.
// These variables are looked up dynamically at runtime. // These variables are looked up dynamically at runtime.
Variable* NonLocal(Handle<String> name, VariableMode mode); Variable* NonLocal(const AstRawString* name, VariableMode mode);
// Variable resolution. // Variable resolution.
// Possible results of a recursive variable lookup telling if and how a // Possible results of a recursive variable lookup telling if and how a
@ -548,7 +551,7 @@ class Scope: public ZoneObject {
// Lookup a variable reference given by name recursively starting with this // 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 // scope. If the code is executed because of a call to 'eval', the context
// parameter should be set to the calling context of 'eval'. // parameter should be set to the calling context of 'eval'.
Variable* LookupRecursive(Handle<String> name, Variable* LookupRecursive(const AstRawString* name,
BindingKind* binding_kind, BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory); AstNodeFactory<AstNullVisitor>* factory);
MUST_USE_RESULT MUST_USE_RESULT
@ -592,10 +595,12 @@ class Scope: public ZoneObject {
private: private:
// Construct a scope based on the scope info. // Construct a scope based on the scope info.
Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> 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. // 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 AstRawString* catch_variable_name,
AstValueFactory* value_factory, Zone* zone);
void AddInnerScope(Scope* inner_scope) { void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) { if (inner_scope != NULL) {
@ -608,6 +613,7 @@ class Scope: public ZoneObject {
Scope* outer_scope, Scope* outer_scope,
Handle<ScopeInfo> scope_info); Handle<ScopeInfo> scope_info);
AstValueFactory* ast_value_factory_;
Zone* zone_; Zone* zone_;
}; };

View File

@ -394,4 +394,24 @@ void init_memcopy_functions() {
} }
bool DoubleToBoolean(double d) {
// NaN, +0, and -0 should return the false object
#if __BYTE_ORDER == __LITTLE_ENDIAN
union IeeeDoubleLittleEndianArchType u;
#elif __BYTE_ORDER == __BIG_ENDIAN
union IeeeDoubleBigEndianArchType u;
#endif
u.d = d;
if (u.bits.exp == 2047) {
// Detect NaN for IEEE double precision floating point.
if ((u.bits.man_low | u.bits.man_high) != 0) return false;
}
if (u.bits.exp == 0) {
// Detect +0, and -0 for IEEE double precision floating point.
if ((u.bits.man_low | u.bits.man_high) == 0) return false;
}
return true;
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -1582,6 +1582,36 @@ class StringBuilder : public SimpleStringBuilder {
}; };
bool DoubleToBoolean(double d);
template <typename Stream>
bool StringToArrayIndex(Stream* stream, uint32_t* index) {
uint16_t ch = stream->GetNext();
// If the string begins with a '0' character, it must only consist
// of it to be a legal array index.
if (ch == '0') {
*index = 0;
return !stream->HasMore();
}
// Convert string to uint32 array index; character by character.
int d = ch - '0';
if (d < 0 || d > 9) return false;
uint32_t result = d;
while (stream->HasMore()) {
d = stream->GetNext() - '0';
if (d < 0 || d > 9) return false;
// Check that the new result is below the 32 bit limit.
if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
result = (result * 10) + d;
}
*index = result;
return true;
}
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_UTILS_H_ #endif // V8_UTILS_H_

View File

@ -33,7 +33,7 @@ const char* Variable::Mode2String(VariableMode mode) {
Variable::Variable(Scope* scope, Variable::Variable(Scope* scope,
Handle<String> name, const AstRawString* name,
VariableMode mode, VariableMode mode,
bool is_valid_ref, bool is_valid_ref,
Kind kind, Kind kind,
@ -52,8 +52,6 @@ Variable::Variable(Scope* scope,
is_used_(false), is_used_(false),
initialization_flag_(initialization_flag), initialization_flag_(initialization_flag),
interface_(interface) { interface_(interface) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsInternalizedString());
// Var declared variables never need initialization. // Var declared variables never need initialization.
ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization)); ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
} }

View File

@ -5,6 +5,7 @@
#ifndef V8_VARIABLES_H_ #ifndef V8_VARIABLES_H_
#define V8_VARIABLES_H_ #define V8_VARIABLES_H_
#include "src/ast-value-factory.h"
#include "src/interface.h" #include "src/interface.h"
#include "src/zone.h" #include "src/zone.h"
@ -52,7 +53,7 @@ class Variable: public ZoneObject {
}; };
Variable(Scope* scope, Variable(Scope* scope,
Handle<String> name, const AstRawString* name,
VariableMode mode, VariableMode mode,
bool is_valid_ref, bool is_valid_ref,
Kind kind, Kind kind,
@ -70,7 +71,8 @@ class Variable: public ZoneObject {
// scope is only used to follow the context chain length. // scope is only used to follow the context chain length.
Scope* scope() const { return scope_; } Scope* scope() const { return scope_; }
Handle<String> name() const { return name_; } Handle<String> name() const { return name_->string(); }
const AstRawString* raw_name() const { return name_; }
VariableMode mode() const { return mode_; } VariableMode mode() const { return mode_; }
bool has_forced_context_allocation() const { bool has_forced_context_allocation() const {
return force_context_allocation_; return force_context_allocation_;
@ -136,7 +138,7 @@ class Variable: public ZoneObject {
private: private:
Scope* scope_; Scope* scope_;
Handle<String> name_; const AstRawString* name_;
VariableMode mode_; VariableMode mode_;
Kind kind_; Kind kind_;
Location location_; Location location_;

View File

@ -41,7 +41,7 @@ TEST(List) {
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate); Zone zone(isolate);
AstNodeFactory<AstNullVisitor> factory(&zone); AstNodeFactory<AstNullVisitor> factory(&zone, NULL);
AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition); AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
list->Add(node); list->Add(node);
CHECK_EQ(1, list->length()); CHECK_EQ(1, list->length());

View File

@ -31,6 +31,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/ast-value-factory.h"
#include "src/compiler.h" #include "src/compiler.h"
#include "src/execution.h" #include "src/execution.h"
#include "src/isolate.h" #include "src/isolate.h"
@ -796,8 +797,12 @@ void TestScanRegExp(const char* re_source, const char* expected) {
CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV); CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV)); CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
scanner.Next(); // Current token is now the regexp literal. scanner.Next(); // Current token is now the regexp literal.
i::Zone zone(CcTest::i_isolate());
i::AstValueFactory ast_value_factory(&zone,
CcTest::i_isolate()->heap()->HashSeed());
ast_value_factory.Internalize(CcTest::i_isolate());
i::Handle<i::String> val = i::Handle<i::String> val =
scanner.AllocateInternalizedString(CcTest::i_isolate()); scanner.CurrentSymbol(&ast_value_factory)->string();
i::DisallowHeapAllocation no_alloc; i::DisallowHeapAllocation no_alloc;
i::String::FlatContent content = val->GetFlatContent(); i::String::FlatContent content = val->GetFlatContent();
CHECK(content.IsAscii()); CHECK(content.IsAscii());
@ -2587,3 +2592,20 @@ TEST(FuncNameInferrerEscaped) {
i::DeleteArray(two_byte_source); i::DeleteArray(two_byte_source);
i::DeleteArray(two_byte_name); i::DeleteArray(two_byte_name);
} }
TEST(RegressionLazyFunctionWithErrorWithArg) {
// The bug occurred when a lazy function had an error which requires a
// parameter (such as "unknown label" here). The error message was processed
// before the AstValueFactory containing the error message string was
// internalized.
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
i::FLAG_lazy = true;
i::FLAG_min_preparse_length = 0;
CompileRun("function this_is_lazy() {\n"
" break p;\n"
"}\n"
"this_is_lazy();\n");
}

View File

@ -343,6 +343,8 @@
'../../src/assembler.h', '../../src/assembler.h',
'../../src/assert-scope.h', '../../src/assert-scope.h',
'../../src/assert-scope.cc', '../../src/assert-scope.cc',
'../../src/ast-value-factory.cc',
'../../src/ast-value-factory.h',
'../../src/ast.cc', '../../src/ast.cc',
'../../src/ast.h', '../../src/ast.h',
'../../src/bignum-dtoa.cc', '../../src/bignum-dtoa.cc',

View File

@ -44,6 +44,18 @@
using namespace v8::internal; 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( std::pair<TimeDelta, TimeDelta> RunBaselineParser(
const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate, const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate,
v8::Handle<v8::Context> context) { v8::Handle<v8::Context> context) {
@ -63,7 +75,9 @@ std::pair<TimeDelta, TimeDelta> RunBaselineParser(
break; break;
} }
case LATIN1: { 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; break;
} }
} }