Parser: Delay internalizing strings and values.

This is needed so that we can run Parser on a non-main thread (independent
of the Isolate and the V8 heap).

BUG=
R=rossberg@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21841 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
marja@chromium.org 2014-06-13 13:31:56 +00:00
parent 7005abf03b
commit a290cf8cda
32 changed files with 1508 additions and 641 deletions

View File

@ -5543,7 +5543,7 @@ class Internals {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
static const int kEmptyStringRootIndex = 163;
static const int kEmptyStringRootIndex = 160;
// The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory.

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

@ -0,0 +1,368 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/ast-value-factory.h"
#include "src/api.h"
#include "src/objects.h"
namespace v8 {
namespace internal {
namespace {
template <typename Char>
int vector_hash(Vector<const Char> string) {
int hash = 0;
for (int i = 0; i < string.length(); i++) {
int c = static_cast<int>(string[i]);
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
// For using StringToArrayIndex.
class OneByteStringStream {
public:
explicit OneByteStringStream(Vector<const byte> lb) :
literal_bytes_(lb), pos_(0) {}
bool HasMore() { return pos_ < literal_bytes_.length(); }
uint16_t GetNext() { return literal_bytes_[pos_++]; }
private:
Vector<const byte> literal_bytes_;
int pos_;
};
}
bool AstString::AsArrayIndex(uint32_t* index) const {
if (!string_.is_null())
return string_->AsArrayIndex(index);
if (!is_one_byte_ || literal_bytes_.length() == 0 ||
literal_bytes_.length() > String::kMaxArrayIndexSize)
return false;
OneByteStringStream stream(literal_bytes_);
return StringToArrayIndex(&stream, index);
}
bool AstString::IsOneByteEqualTo(const char* data) const {
int length = strlen(data);
if (is_one_byte_ && literal_bytes_.length() == length) {
const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
return !strncmp(token, data, length);
}
return false;
}
void AstString::Internalize(Isolate* isolate) {
if (!string_.is_null()) return;
if (literal_bytes_.length() == 0) {
string_ = isolate->factory()->empty_string();
} else if (is_one_byte_) {
string_ = isolate->factory()->InternalizeOneByteString(literal_bytes_);
} else {
string_ = isolate->factory()->InternalizeTwoByteString(
Vector<const uint16_t>::cast(literal_bytes_));
}
}
bool AstString::Compare(void* a, void* b) {
AstString* string1 = reinterpret_cast<AstString*>(a);
AstString* string2 = reinterpret_cast<AstString*>(b);
if (string1->is_one_byte_ != string2->is_one_byte_) return false;
if (string1->hash_ != string2->hash_) return false;
int length = string1->literal_bytes_.length();
if (string2->literal_bytes_.length() != length) return false;
return memcmp(string1->literal_bytes_.start(),
string2->literal_bytes_.start(), length) == 0;
}
bool AstValue::IsPropertyName() const {
if (type_ == STRING) {
uint32_t index;
return !string_->AsArrayIndex(&index);
}
return false;
}
bool AstValue::BooleanValue() const {
switch (type_) {
case STRING:
ASSERT(string_ != NULL);
return !string_->IsEmpty();
case SYMBOL:
UNREACHABLE();
break;
case NUMBER:
return DoubleToBoolean(number_);
case SMI:
return smi_ != 0;
case STRING_ARRAY:
UNREACHABLE();
break;
case BOOLEAN:
return bool_;
case NULL_TYPE:
return false;
case THE_HOLE:
UNREACHABLE();
break;
case UNDEFINED:
return false;
}
UNREACHABLE();
return false;
}
void AstValue::Internalize(Isolate* isolate) {
switch (type_) {
case STRING:
ASSERT(string_ != NULL);
// Strings are already internalized.
ASSERT(!string_->string().is_null());
break;
case SYMBOL:
value_ = Object::GetProperty(
isolate, handle(isolate->native_context()->builtins()),
symbol_name_).ToHandleChecked();
break;
case NUMBER:
value_ = isolate->factory()->NewNumber(number_, TENURED);
break;
case SMI:
value_ = handle(Smi::FromInt(smi_), isolate);
break;
case BOOLEAN:
if (bool_) {
value_ = isolate->factory()->true_value();
} else {
value_ = isolate->factory()->false_value();
}
break;
case STRING_ARRAY: {
ASSERT(strings_ != NULL);
Factory* factory = isolate->factory();
int len = strings_->length();
Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
for (int i = 0; i < len; i++) {
const AstString* string = (*strings_)[i];
Handle<Object> element = string->string();
// Strings are already internalized.
ASSERT(!element.is_null());
elements->set(i, *element);
}
value_ =
factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
break;
}
case NULL_TYPE:
value_ = isolate->factory()->null_value();
break;
case THE_HOLE:
value_ = isolate->factory()->the_hole_value();
break;
case UNDEFINED:
value_ = isolate->factory()->undefined_value();
break;
}
}
const AstString* AstValueFactory::GetOneByteString(
Vector<const uint8_t> literal) {
return GetString(vector_hash(literal), true, literal);
}
const AstString* AstValueFactory::GetTwoByteString(
Vector<const uint16_t> literal) {
return GetString(vector_hash(literal), false,
Vector<const byte>::cast(literal));
}
const AstString* AstValueFactory::GetString(Handle<String> literal) {
DisallowHeapAllocation no_gc;
String::FlatContent content = literal->GetFlatContent();
if (content.IsAscii()) {
return GetOneByteString(content.ToOneByteVector());
}
ASSERT(content.IsTwoByte());
return GetTwoByteString(content.ToUC16Vector());
}
void AstValueFactory::Internalize(Isolate* isolate) {
if (isolate_) {
// Everything is already internalized.
return;
}
// Strings need to be internalized before values, because values refer to
// strings.
for (HashMap::Entry* p = string_table_.Start(); p != NULL;
p = string_table_.Next(p)) {
AstString* string = reinterpret_cast<AstString*>(p->key);
string->Internalize(isolate);
}
for (int i = 0; i < values_.length(); ++i) {
values_[i]->Internalize(isolate);
}
isolate_ = isolate;
}
const AstValue* AstValueFactory::NewString(const AstString* string) {
AstValue* value = new (zone_) AstValue(string);
ASSERT(string != NULL);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewSymbol(const char* name) {
AstValue* value = new (zone_) AstValue(name);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewNumber(double number) {
AstValue* value = new (zone_) AstValue(number);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewSmi(int number) {
AstValue* value =
new (zone_) AstValue(AstValue::SMI, number);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewBoolean(bool b) {
AstValue* value = new (zone_) AstValue(b);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewStringList(
ZoneList<const AstString*>* strings) {
AstValue* value = new (zone_) AstValue(strings);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewNull() {
AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewUndefined() {
AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstValue* AstValueFactory::NewTheHole() {
AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
if (isolate_) {
value->Internalize(isolate_);
}
values_.Add(value);
return value;
}
const AstString* AstValueFactory::GetString(int hash, bool is_one_byte,
Vector<const byte> literal_bytes) {
// literal_bytes here points to whatever the user passed, and this is OK
// because we use vector_compare (which checks the contents) to compare
// against the AstStrings which are in the string_table_. We should not return
// this AstString.
AstString key(is_one_byte, literal_bytes, hash);
HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
if (entry->value == NULL) {
// Copy literal contents for later comparison.
key.literal_bytes_ =
Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
// This Vector will be valid as long as the Collector is alive (meaning that
// the AstString will not be moved).
Vector<AstString> new_string = string_table_keys_.AddBlock(1, key);
entry->key = &new_string[0];
if (isolate_) {
new_string[0].Internalize(isolate_);
}
entry->value = reinterpret_cast<void*>(1);
}
return reinterpret_cast<AstString*>(entry->key);
}
} } // namespace v8::internal

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

@ -0,0 +1,294 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_AST_VALUE_FACTORY_H_
#define V8_AST_VALUE_FACTORY_H_
#include "src/api.h"
#include "src/hashmap.h"
#include "src/utils.h"
// AstString, AstValue and AstValueFactory are for storing strings and values
// independent of the V8 heap and internalizing them later. During parsing,
// AstStrings and AstValues are created and stored outside the heap, in
// AstValueFactory. After parsing, the strings and values are internalized
// (moved into the V8 heap).
namespace v8 {
namespace internal {
class AstString {
public:
AstString(bool i, Vector<const byte> lb, int h)
: is_one_byte_(i),
literal_bytes_(lb),
hash_(h) {}
AstString()
: is_one_byte_(true),
hash_(0) {}
bool AsArrayIndex(uint32_t* index) const;
// The string is not null-terminated, use length() to find out the length.
const unsigned char* raw_data() const { return literal_bytes_.start(); }
int length() const {
if (is_one_byte_)
return literal_bytes_.length();
return literal_bytes_.length() / 2;
}
bool is_one_byte() const { return is_one_byte_; }
bool IsEmpty() const { return literal_bytes_.length() == 0; }
bool IsOneByteEqualTo(const char* data) const;
uint16_t FirstCharacter() const {
if (is_one_byte_)
return literal_bytes_[0];
const uint16_t* c =
reinterpret_cast<const uint16_t*>(literal_bytes_.start());
return *c;
}
// Puts the string into the V8 heap.
void Internalize(Isolate* isolate);
// This function can be called after internalizing.
V8_INLINE Handle<String> string() const {
ASSERT(!string_.is_null());
return string_;
}
// For storing AstStrings in a hash map.
int hash() const { return hash_; }
static bool Compare(void* a, void* b);
private:
friend class AstValueFactory;
bool is_one_byte_;
// Weak. Points to memory owned by AstValueFactory.
Vector<const byte> literal_bytes_;
int hash_;
// This is null until the string is internalized.
Handle<String> string_;
};
// AstValue is either a string, a number, a string array, a boolean, or a
// special value (null, undefined, the hole).
class AstValue : public ZoneObject {
public:
bool IsString() const {
return type_ == STRING;
}
bool IsNumber() const {
return type_ == NUMBER || type_ == SMI;
}
const AstString* AsString() const {
if (type_ == STRING)
return string_;
UNREACHABLE();
return 0;
}
double AsNumber() const {
if (type_ == NUMBER)
return number_;
if (type_ == SMI)
return smi_;
UNREACHABLE();
return 0;
}
bool EqualsString(const AstString* string) const {
return type_ == STRING && string_ == string;
}
bool IsPropertyName() const;
bool BooleanValue() const;
void Internalize(Isolate* isolate);
// Can be called after Internalize has been called.
V8_INLINE Handle<Object> value() const {
if (type_ == STRING) {
return string_->string();
}
ASSERT(!value_.is_null());
return value_;
}
private:
friend class AstValueFactory;
enum Type {
STRING,
SYMBOL,
NUMBER,
SMI,
BOOLEAN,
STRING_ARRAY,
NULL_TYPE,
UNDEFINED,
THE_HOLE
};
explicit AstValue(const AstString* s) : type_(STRING) { string_ = s; }
explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; }
explicit AstValue(double n) : type_(NUMBER) { number_ = n; }
AstValue(Type t, int i) : type_(t) {
ASSERT(type_ == SMI);
smi_ = i;
}
explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; }
explicit AstValue(ZoneList<const AstString*>* s) : type_(STRING_ARRAY) {
strings_ = s;
}
explicit AstValue(Type t) : type_(t) {
ASSERT(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
}
Type type_;
// Uninternalized value.
union {
const AstString* string_;
double number_;
int smi_;
bool bool_;
ZoneList<const AstString*>* strings_;
const char* symbol_name_;
};
// Internalized value (empty before internalized).
Handle<Object> value_;
};
// For generating string constants.
#define STRING_CONSTANTS(F) \
F(anonymous_function, "(anonymous function)") \
F(arguments, "arguments") \
F(done, "done") \
F(dot_for, ".for") \
F(dot_generator, ".generator") \
F(dot_generator_object, ".generator_object") \
F(dot_iterable, ".iterable") \
F(dot_iterator, ".iterator") \
F(dot_module, ".module") \
F(dot_result, ".result") \
F(empty, "") \
F(eval, "eval") \
F(initialize_const_global, "initializeConstGlobal") \
F(initialize_var_global, "initializeVarGlobal") \
F(make_reference_error, "MakeReferenceError") \
F(make_syntax_error, "MakeSyntaxError") \
F(make_type_error, "MakeTypeError") \
F(module, "module") \
F(native, "native") \
F(next, "next") \
F(proto, "__proto__") \
F(prototype, "prototype") \
F(this, "this") \
F(use_strict, "use strict") \
F(value, "value")
class AstValueFactory {
public:
explicit AstValueFactory(Zone* zone)
: literal_chars_(0),
string_table_keys_(0),
string_table_(AstString::Compare),
zone_(zone),
isolate_(NULL) {
#define F(name, str) { \
const char* data = str; \
name##_string_ = GetOneByteString( \
Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \
strlen(data))); \
}
STRING_CONSTANTS(F)
#undef F
}
const AstString* GetOneByteString(Vector<const uint8_t> literal);
const AstString* GetTwoByteString(Vector<const uint16_t> literal);
const AstString* GetString(Handle<String> literal);
void Internalize(Isolate* isolate);
#define F(name, str) \
const AstString* name##_string() const { return name##_string_; }
STRING_CONSTANTS(F)
#undef F
const AstValue* NewString(const AstString* string);
// A JavaScript symbol (ECMA-262 edition 6).
const AstValue* NewSymbol(const char* name);
const AstValue* NewNumber(double number);
const AstValue* NewSmi(int number);
const AstValue* NewBoolean(bool b);
const AstValue* NewStringList(ZoneList<const AstString*>* strings);
const AstValue* NewNull();
const AstValue* NewUndefined();
const AstValue* NewTheHole();
private:
const AstString* GetString(int hash, bool is_one_byte,
Vector<const byte> literal_bytes);
// All strings are copied here, one after another (no NULLs inbetween).
Collector<byte> literal_chars_;
// List of all AstStrings we have created; keys of string_table_ are pointers
// into AstStrings in string_table_keys_.
Collector<AstString> string_table_keys_;
HashMap string_table_;
// For keeping track of all AstValues we've created (so that they can be
// internalized later).
List<AstValue*> values_;
Zone* zone_;
Isolate* isolate_;
#define F(name, str) \
const AstString* name##_string_;
STRING_CONSTANTS(F)
#undef F
};
} } // namespace v8::internal
#undef STRING_CONSTANTS
#endif // V8_AST_VALUE_FACTORY_H_

View File

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

237
src/ast.h
View File

@ -8,6 +8,7 @@
#include "src/v8.h"
#include "src/assembler.h"
#include "src/ast-value-factory.h"
#include "src/factory.h"
#include "src/feedback-slots.h"
#include "src/isolate.h"
@ -367,11 +368,14 @@ class Expression : public AstNode {
protected:
Expression(Zone* zone, int pos)
: AstNode(pos),
zone_(zone),
bounds_(Bounds::Unbounded(zone)),
id_(GetNextId(zone)),
test_id_(GetNextId(zone)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
Zone* zone_;
private:
Bounds bounds_;
byte to_boolean_types_;
@ -390,7 +394,7 @@ class BreakableStatement : public Statement {
// The labels associated with this statement. May be NULL;
// if it is != NULL, guaranteed to contain at least one entry.
ZoneStringList* labels() const { return labels_; }
ZoneList<const AstString*>* labels() const { return labels_; }
// Type testing & conversion.
virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE {
@ -410,7 +414,7 @@ class BreakableStatement : public Statement {
protected:
BreakableStatement(
Zone* zone, ZoneStringList* labels,
Zone* zone, ZoneList<const AstString*>* labels,
BreakableType breakable_type, int position)
: Statement(zone, position),
labels_(labels),
@ -422,7 +426,7 @@ class BreakableStatement : public Statement {
private:
ZoneStringList* labels_;
ZoneList<const AstString*>* labels_;
BreakableType breakable_type_;
Label break_target_;
const BailoutId entry_id_;
@ -453,7 +457,7 @@ class Block V8_FINAL : public BreakableStatement {
protected:
Block(Zone* zone,
ZoneStringList* labels,
ZoneList<const AstString*>* labels,
int capacity,
bool is_initializer_block,
int pos)
@ -662,18 +666,15 @@ class ModulePath V8_FINAL : public Module {
DECLARE_NODE_TYPE(ModulePath)
Module* module() const { return module_; }
Handle<String> name() const { return name_; }
Handle<String> name() const { return name_->string(); }
protected:
ModulePath(Zone* zone, Module* module, Handle<String> name, int pos)
: Module(zone, pos),
module_(module),
name_(name) {
}
ModulePath(Zone* zone, Module* module, const AstString* name, int pos)
: Module(zone, pos), module_(module), name_(name) {}
private:
Module* module_;
Handle<String> name_;
const AstString* name_;
};
@ -730,7 +731,7 @@ class IterationStatement : public BreakableStatement {
Label* continue_target() { return &continue_target_; }
protected:
IterationStatement(Zone* zone, ZoneStringList* labels, int pos)
IterationStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
body_(NULL),
osr_entry_id_(GetNextId(zone)) {
@ -764,7 +765,7 @@ class DoWhileStatement V8_FINAL : public IterationStatement {
BailoutId BackEdgeId() const { return back_edge_id_; }
protected:
DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos)
DoWhileStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
cond_(NULL),
continue_id_(GetNextId(zone)),
@ -801,7 +802,7 @@ class WhileStatement V8_FINAL : public IterationStatement {
BailoutId BodyId() const { return body_id_; }
protected:
WhileStatement(Zone* zone, ZoneStringList* labels, int pos)
WhileStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
cond_(NULL),
may_have_function_literal_(true),
@ -852,7 +853,7 @@ class ForStatement V8_FINAL : public IterationStatement {
void set_loop_variable(Variable* var) { loop_variable_ = var; }
protected:
ForStatement(Zone* zone, ZoneStringList* labels, int pos)
ForStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
init_(NULL),
cond_(NULL),
@ -894,11 +895,8 @@ class ForEachStatement : public IterationStatement {
Expression* subject() const { return subject_; }
protected:
ForEachStatement(Zone* zone, ZoneStringList* labels, int pos)
: IterationStatement(zone, labels, pos),
each_(NULL),
subject_(NULL) {
}
ForEachStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
private:
Expression* each_;
@ -934,7 +932,7 @@ class ForInStatement V8_FINAL : public ForEachStatement,
virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
protected:
ForInStatement(Zone* zone, ZoneStringList* labels, int pos)
ForInStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: ForEachStatement(zone, labels, pos),
for_in_type_(SLOW_FOR_IN),
for_in_feedback_slot_(kInvalidFeedbackSlot),
@ -1004,7 +1002,7 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
BailoutId BackEdgeId() const { return back_edge_id_; }
protected:
ForOfStatement(Zone* zone, ZoneStringList* labels, int pos)
ForOfStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: ForEachStatement(zone, labels, pos),
assign_iterator_(NULL),
next_result_(NULL),
@ -1165,7 +1163,7 @@ class SwitchStatement V8_FINAL : public BreakableStatement {
ZoneList<CaseClause*>* cases() const { return cases_; }
protected:
SwitchStatement(Zone* zone, ZoneStringList* labels, int pos)
SwitchStatement(Zone* zone, ZoneList<const AstString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
tag_(NULL),
cases_(NULL) { }
@ -1345,26 +1343,28 @@ class Literal V8_FINAL : public Expression {
DECLARE_NODE_TYPE(Literal)
virtual bool IsPropertyName() const V8_OVERRIDE {
if (value_->IsInternalizedString()) {
uint32_t ignored;
return !String::cast(*value_)->AsArrayIndex(&ignored);
}
return false;
return value_->IsPropertyName();
}
Handle<String> AsPropertyName() {
ASSERT(IsPropertyName());
return Handle<String>::cast(value_);
return Handle<String>::cast(value());
}
const AstString* AsRawPropertyName() {
ASSERT(IsPropertyName());
return value_->AsString();
}
virtual bool ToBooleanIsTrue() const V8_OVERRIDE {
return value_->BooleanValue();
return value()->BooleanValue();
}
virtual bool ToBooleanIsFalse() const V8_OVERRIDE {
return !value_->BooleanValue();
return !value()->BooleanValue();
}
Handle<Object> value() const { return value_; }
Handle<Object> value() const { return value_->value(); }
const AstValue* raw_value() const { return value_; }
// Support for using Literal as a HashMap key. NOTE: Currently, this works
// only for string and number literals!
@ -1379,7 +1379,7 @@ class Literal V8_FINAL : public Expression {
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
protected:
Literal(Zone* zone, Handle<Object> value, int position)
Literal(Zone* zone, const AstValue* value, int position)
: Expression(zone, position),
value_(value),
isolate_(zone->isolate()) { }
@ -1387,7 +1387,7 @@ class Literal V8_FINAL : public Expression {
private:
Handle<String> ToString();
Handle<Object> value_;
const AstValue* value_;
// TODO(dcarney): remove. this is only needed for Match and Hash.
Isolate* isolate_;
};
@ -1458,7 +1458,8 @@ class ObjectLiteralProperty V8_FINAL : public ZoneObject {
PROTOTYPE // Property is __proto__.
};
ObjectLiteralProperty(Zone* zone, Literal* key, Expression* value);
ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory,
Literal* key, Expression* value);
Literal* key() { return key_; }
Expression* value() { return value_; }
@ -1557,13 +1558,13 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
public:
DECLARE_NODE_TYPE(RegExpLiteral)
Handle<String> pattern() const { return pattern_; }
Handle<String> flags() const { return flags_; }
Handle<String> pattern() const { return pattern_->string(); }
Handle<String> flags() const { return flags_->string(); }
protected:
RegExpLiteral(Zone* zone,
Handle<String> pattern,
Handle<String> flags,
const AstString* pattern,
const AstString* flags,
int literal_index,
int pos)
: MaterializedLiteral(zone, literal_index, pos),
@ -1573,8 +1574,8 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
}
private:
Handle<String> pattern_;
Handle<String> flags_;
const AstString* pattern_;
const AstString* flags_;
};
@ -1625,15 +1626,12 @@ class VariableProxy V8_FINAL : public Expression {
return var_ == NULL ? true : var_->IsValidReference();
}
bool IsVariable(Handle<String> n) const {
return !is_this() && name().is_identical_to(n);
}
bool IsArguments() const { return var_ != NULL && var_->is_arguments(); }
bool IsLValue() const { return is_lvalue_; }
Handle<String> name() const { return name_; }
Handle<String> name() const { return name_->string(); }
const AstString* raw_name() const { return name_; }
Variable* var() const { return var_; }
bool is_this() const { return is_this_; }
Interface* interface() const { return interface_; }
@ -1649,12 +1647,12 @@ class VariableProxy V8_FINAL : public Expression {
VariableProxy(Zone* zone, Variable* var, int position);
VariableProxy(Zone* zone,
Handle<String> name,
const AstString* name,
bool is_this,
Interface* interface,
int position);
Handle<String> name_;
const AstString* name_;
Variable* var_; // resolved variable, or NULL
bool is_this_;
bool is_trivial_;
@ -1900,7 +1898,8 @@ class CallRuntime V8_FINAL : public Expression {
public:
DECLARE_NODE_TYPE(CallRuntime)
Handle<String> name() const { return name_; }
Handle<String> name() const { return raw_name_->string(); }
const AstString* raw_name() const { return raw_name_; }
const Runtime::Function* function() const { return function_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
bool is_jsruntime() const { return function_ == NULL; }
@ -1909,17 +1908,17 @@ class CallRuntime V8_FINAL : public Expression {
protected:
CallRuntime(Zone* zone,
Handle<String> name,
const AstString* name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments,
int pos)
: Expression(zone, pos),
name_(name),
raw_name_(name),
function_(function),
arguments_(arguments) { }
private:
Handle<String> name_;
const AstString* raw_name_;
const Runtime::Function* function_;
ZoneList<Expression*>* arguments_;
};
@ -2307,7 +2306,8 @@ class FunctionLiteral V8_FINAL : public Expression {
DECLARE_NODE_TYPE(FunctionLiteral)
Handle<String> name() const { return name_; }
Handle<String> name() const { return raw_name_->string(); }
const AstString* raw_name() const { return raw_name_; }
Scope* scope() const { return scope_; }
ZoneList<Statement*>* body() const { return body_; }
void set_function_token_position(int pos) { function_token_position_ = pos; }
@ -2330,13 +2330,35 @@ class FunctionLiteral V8_FINAL : public Expression {
void InitializeSharedInfo(Handle<Code> code);
Handle<String> debug_name() const {
if (name_->length() > 0) return name_;
if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
return raw_name_->string();
}
return inferred_name();
}
Handle<String> inferred_name() const { return inferred_name_; }
Handle<String> inferred_name() const {
if (!inferred_name_.is_null()) {
ASSERT(raw_inferred_name_ == NULL);
return inferred_name_;
}
if (raw_inferred_name_ != NULL) {
return raw_inferred_name_->string();
}
UNREACHABLE();
return Handle<String>();
}
// Only one of {set_inferred_name, set_raw_inferred_name} should be called.
void set_inferred_name(Handle<String> inferred_name) {
inferred_name_ = inferred_name;
ASSERT(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty());
raw_inferred_name_ = NULL;
}
void set_raw_inferred_name(const AstString* raw_inferred_name) {
raw_inferred_name_ = raw_inferred_name;
ASSERT(inferred_name_.is_null());
inferred_name_ = Handle<String>();
}
// shared_info may be null if it's not cached in full code.
@ -2383,7 +2405,8 @@ class FunctionLiteral V8_FINAL : public Expression {
protected:
FunctionLiteral(Zone* zone,
Handle<String> name,
const AstString* name,
AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@ -2397,10 +2420,10 @@ class FunctionLiteral V8_FINAL : public Expression {
IsGeneratorFlag is_generator,
int position)
: Expression(zone, position),
name_(name),
raw_name_(name),
scope_(scope),
body_(body),
inferred_name_(zone->isolate()->factory()->empty_string()),
raw_inferred_name_(ast_value_factory->empty_string()),
dont_optimize_reason_(kNoReason),
materialized_literal_count_(materialized_literal_count),
expected_property_count_(expected_property_count),
@ -2418,10 +2441,12 @@ class FunctionLiteral V8_FINAL : public Expression {
}
private:
const AstString* raw_name_;
Handle<String> name_;
Handle<SharedFunctionInfo> shared_info_;
Scope* scope_;
ZoneList<Statement*>* body_;
const AstString* raw_inferred_name_;
Handle<String> inferred_name_;
AstProperties ast_properties_;
BailoutReason dont_optimize_reason_;
@ -2447,16 +2472,16 @@ class NativeFunctionLiteral V8_FINAL : public Expression {
public:
DECLARE_NODE_TYPE(NativeFunctionLiteral)
Handle<String> name() const { return name_; }
Handle<String> name() const { return name_->string(); }
v8::Extension* extension() const { return extension_; }
protected:
NativeFunctionLiteral(
Zone* zone, Handle<String> name, v8::Extension* extension, int pos)
NativeFunctionLiteral(Zone* zone, const AstString* name,
v8::Extension* extension, int pos)
: Expression(zone, pos), name_(name), extension_(extension) {}
private:
Handle<String> name_;
const AstString* name_;
v8::Extension* extension_;
};
@ -2948,7 +2973,8 @@ class AstNullVisitor BASE_EMBEDDED {
template<class Visitor>
class AstNodeFactory V8_FINAL BASE_EMBEDDED {
public:
explicit AstNodeFactory(Zone* zone) : zone_(zone) { }
explicit AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory)
: zone_(zone), ast_value_factory_(ast_value_factory) {}
Visitor* visitor() { return &visitor_; }
@ -3012,8 +3038,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(ModuleVariable, module)
}
ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) {
ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos);
ModulePath* NewModulePath(Module* origin, const AstString* name, int pos) {
ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos);
VISIT_AND_RETURN(ModulePath, module)
}
@ -3022,7 +3048,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(ModuleUrl, module)
}
Block* NewBlock(ZoneStringList* labels,
Block* NewBlock(ZoneList<const AstString*>* labels,
int capacity,
bool is_initializer_block,
int pos) {
@ -3032,7 +3058,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
}
#define STATEMENT_WITH_LABELS(NodeType) \
NodeType* New##NodeType(ZoneStringList* labels, int pos) { \
NodeType* New##NodeType(ZoneList<const AstString*>* labels, int pos) { \
NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \
VISIT_AND_RETURN(NodeType, stmt); \
}
@ -3043,7 +3069,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
#undef STATEMENT_WITH_LABELS
ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
ZoneStringList* labels,
ZoneList<const AstString*>* labels,
int pos) {
switch (visit_mode) {
case ForEachStatement::ENUMERATE: {
@ -3140,14 +3166,59 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(CaseClause, clause)
}
Literal* NewLiteral(Handle<Object> handle, int pos) {
Literal* lit = new(zone_) Literal(zone_, handle, pos);
Literal* NewStringLiteral(const AstString* string, int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos);
VISIT_AND_RETURN(Literal, lit)
}
// A JavaScript symbol (ECMA-262 edition 6).
Literal* NewSymbolLiteral(const char* name, int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewNumberLiteral(double number, int pos) {
return NewLiteral(
zone_->isolate()->factory()->NewNumber(number, TENURED), pos);
Literal* lit = new (zone_)
Literal(zone_, ast_value_factory_->NewNumber(number), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewSmiLiteral(int number, int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewBooleanLiteral(bool b, int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewStringListLiteral(ZoneList<const AstString*>* strings, int pos) {
Literal* lit = new (zone_)
Literal(zone_, ast_value_factory_->NewStringList(strings), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewNullLiteral(int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewUndefinedLiteral(int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewTheHoleLiteral(int pos) {
Literal* lit =
new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos);
VISIT_AND_RETURN(Literal, lit)
}
ObjectLiteral* NewObjectLiteral(
@ -3164,7 +3235,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
Expression* value) {
return new(zone_) ObjectLiteral::Property(zone_, key, value);
return new (zone_)
ObjectLiteral::Property(zone_, ast_value_factory_, key, value);
}
ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
@ -3172,12 +3244,12 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
int pos) {
ObjectLiteral::Property* prop =
new(zone_) ObjectLiteral::Property(zone_, is_getter, value);
prop->set_key(NewLiteral(value->name(), pos));
prop->set_key(NewStringLiteral(value->raw_name(), pos));
return prop; // Not an AST node, will not be visited.
}
RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
Handle<String> flags,
RegExpLiteral* NewRegExpLiteral(const AstString* pattern,
const AstString* flags,
int literal_index,
int pos) {
RegExpLiteral* lit =
@ -3199,7 +3271,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(VariableProxy, proxy)
}
VariableProxy* NewVariableProxy(Handle<String> name,
VariableProxy* NewVariableProxy(const AstString* name,
bool is_this,
Interface* interface = Interface::NewValue(),
int position = RelocInfo::kNoPosition) {
@ -3227,7 +3299,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(CallNew, call)
}
CallRuntime* NewCallRuntime(Handle<String> name,
CallRuntime* NewCallRuntime(const AstString* name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments,
int pos) {
@ -3305,7 +3377,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
}
FunctionLiteral* NewFunctionLiteral(
Handle<String> name,
const AstString* name,
AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@ -3319,7 +3392,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
FunctionLiteral::IsGeneratorFlag is_generator,
int position) {
FunctionLiteral* lit = new(zone_) FunctionLiteral(
zone_, name, scope, body,
zone_, name, ast_value_factory, scope, body,
materialized_literal_count, expected_property_count, handler_count,
parameter_count, function_type, has_duplicate_parameters, is_function,
is_parenthesized, is_generator, position);
@ -3331,7 +3404,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
}
NativeFunctionLiteral* NewNativeFunctionLiteral(
Handle<String> name, v8::Extension* extension, int pos) {
const AstString* name, v8::Extension* extension,
int pos) {
NativeFunctionLiteral* lit =
new(zone_) NativeFunctionLiteral(zone_, name, extension, pos);
VISIT_AND_RETURN(NativeFunctionLiteral, lit)
@ -3347,6 +3421,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
private:
Zone* zone_;
Visitor visitor_;
AstValueFactory* ast_value_factory_;
};

View File

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

View File

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

View File

@ -5,14 +5,16 @@
#include "src/v8.h"
#include "src/ast.h"
#include "src/ast-value-factory.h"
#include "src/func-name-inferrer.h"
#include "src/list-inl.h"
namespace v8 {
namespace internal {
FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
: isolate_(isolate),
FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
Zone* zone)
: ast_value_factory_(ast_value_factory),
entries_stack_(10, zone),
names_stack_(5, zone),
funcs_to_infer_(4, zone),
@ -20,66 +22,119 @@ FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
}
void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
void FuncNameInferrer::PushEnclosingName(const AstString* name) {
// Enclosing name is a name of a constructor function. To check
// that it is really a constructor, we check that it is not empty
// and starts with a capital letter.
if (name->length() > 0 && Runtime::IsUpperCaseChar(
isolate()->runtime_state(), name->Get(0))) {
if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
}
}
void FuncNameInferrer::PushLiteralName(Handle<String> name) {
if (IsOpen() &&
!String::Equals(isolate()->factory()->prototype_string(), name)) {
void FuncNameInferrer::PushLiteralName(const AstString* name) {
if (IsOpen() && name != ast_value_factory_->prototype_string()) {
names_stack_.Add(Name(name, kLiteralName), zone());
}
}
void FuncNameInferrer::PushVariableName(Handle<String> name) {
if (IsOpen() &&
!String::Equals(isolate()->factory()->dot_result_string(), name)) {
void FuncNameInferrer::PushVariableName(const AstString* name) {
if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
names_stack_.Add(Name(name, kVariableName), zone());
}
}
Handle<String> FuncNameInferrer::MakeNameFromStack() {
return MakeNameFromStackHelper(0, isolate()->factory()->empty_string());
}
Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
Handle<String> prev) {
if (pos >= names_stack_.length()) return prev;
if (pos < names_stack_.length() - 1 &&
names_stack_.at(pos).type == kVariableName &&
names_stack_.at(pos + 1).type == kVariableName) {
// Skip consecutive variable declarations.
return MakeNameFromStackHelper(pos + 1, prev);
} else {
if (prev->length() > 0) {
Handle<String> name = names_stack_.at(pos).name;
if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
Factory* factory = isolate()->factory();
Handle<String> curr =
factory->NewConsString(factory->dot_string(), name).ToHandleChecked();
curr = factory->NewConsString(prev, curr).ToHandleChecked();
return MakeNameFromStackHelper(pos + 1, curr);
} else {
return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
const AstString* FuncNameInferrer::MakeNameFromStack() {
// First see how many names we will use.
int length = 0;
bool one_byte = true;
int pos = 0;
while (pos < names_stack_.length()) {
if (pos < names_stack_.length() - 1 &&
names_stack_.at(pos).type == kVariableName &&
names_stack_.at(pos + 1).type == kVariableName) {
// Skip consecutive variable declarations.
++pos;
continue;
}
int cur_length = names_stack_.at(pos).name->length();
if (length + 1 + cur_length > String::kMaxLength) {
break;
}
if (length == 0) {
length = cur_length;
} else { // Add the . between names.
length += (1 + cur_length);
}
one_byte = one_byte && names_stack_.at(pos).name->is_one_byte();
++pos;
}
const AstString* to_return = NULL;
const char* dot = ".";
if (one_byte) {
Vector<uint8_t> new_name = Vector<uint8_t>::New(length);
int name_pos = 0;
for (int i = 0; i < pos; ++i) {
if (i < names_stack_.length() - 1 &&
names_stack_.at(i).type == kVariableName &&
names_stack_.at(i + 1).type == kVariableName) {
// Skip consecutive variable declarations.
continue;
}
if (name_pos != 0) {
CopyChars(new_name.start() + name_pos, dot, 1);
++name_pos;
}
CopyChars(new_name.start() + name_pos,
names_stack_.at(i).name->raw_data(),
names_stack_.at(i).name->length());
name_pos += names_stack_.at(i).name->length();
}
to_return = ast_value_factory_->GetOneByteString(Vector<const uint8_t>(
reinterpret_cast<const uint8_t*>(new_name.start()),
new_name.length()));
new_name.Dispose();
} else {
Vector<uint16_t> new_name = Vector<uint16_t>::New(length);
int name_pos = 0;
for (int i = 0; i < pos; ++i) {
if (i < names_stack_.length() - 1 &&
names_stack_.at(i).type == kVariableName &&
names_stack_.at(i + 1).type == kVariableName) {
// Skip consecutive variable declarations.
continue;
}
if (name_pos != 0) {
CopyChars(new_name.start() + name_pos, dot, 1);
++name_pos;
}
if (names_stack_.at(i).name->is_one_byte()) {
CopyChars(new_name.start() + name_pos,
names_stack_.at(i).name->raw_data(),
names_stack_.at(i).name->length());
} else {
CopyChars(new_name.start() + name_pos,
reinterpret_cast<const uint16_t*>(
names_stack_.at(i).name->raw_data()),
names_stack_.at(i).name->length());
}
name_pos += names_stack_.at(i).name->length();
}
to_return = ast_value_factory_->GetTwoByteString(Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(new_name.start()),
new_name.length()));
new_name.Dispose();
}
return to_return;
}
void FuncNameInferrer::InferFunctionsNames() {
Handle<String> func_name = MakeNameFromStack();
const AstString* func_name = MakeNameFromStack();
for (int i = 0; i < funcs_to_infer_.length(); ++i) {
funcs_to_infer_[i]->set_inferred_name(func_name);
funcs_to_infer_[i]->set_raw_inferred_name(func_name);
}
funcs_to_infer_.Rewind(0);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1716,22 +1716,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
bool HeapNumber::HeapNumberBooleanValue() {
// NaN, +0, and -0 should return the false object
#if __BYTE_ORDER == __LITTLE_ENDIAN
union IeeeDoubleLittleEndianArchType u;
#elif __BYTE_ORDER == __BIG_ENDIAN
union IeeeDoubleBigEndianArchType u;
#endif
u.d = value();
if (u.bits.exp == 2047) {
// Detect NaN for IEEE double precision floating point.
if ((u.bits.man_low | u.bits.man_high) != 0) return false;
}
if (u.bits.exp == 0) {
// Detect +0, and -0 for IEEE double precision floating point.
if ((u.bits.man_low | u.bits.man_high) == 0) return false;
}
return true;
return DoubleToBoolean(value());
}
@ -9352,29 +9337,7 @@ bool String::ComputeArrayIndex(uint32_t* index) {
if (length == 0 || length > kMaxArrayIndexSize) return false;
ConsStringIteratorOp op;
StringCharacterStream stream(this, &op);
uint16_t ch = stream.GetNext();
// If the string begins with a '0' character, it must only consist
// of it to be a legal array index.
if (ch == '0') {
*index = 0;
return length == 1;
}
// Convert string to uint32 array index; character by character.
int d = ch - '0';
if (d < 0 || d > 9) return false;
uint32_t result = d;
while (stream.HasMore()) {
d = stream.GetNext() - '0';
if (d < 0 || d > 9) return false;
// Check that the new result is below the 32 bit limit.
if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
result = (result * 10) + d;
}
*index = result;
return true;
return StringToArrayIndex(&stream, index);
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -149,7 +149,8 @@ class ParserBase : public Traits {
FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope,
typename Traits::Type::Zone* zone = NULL);
typename Traits::Type::Zone* zone = NULL,
AstValueFactory* ast_value_factory = NULL);
~FunctionState();
int NextMaterializedLiteralIndex() {
@ -356,7 +357,9 @@ class ParserBase : public Traits {
void ReportMessageAt(Scanner::Location location, const char* message,
bool is_reference_error = false) {
Traits::ReportMessageAt(location, message, NULL, is_reference_error);
Traits::ReportMessageAt(location, message,
reinterpret_cast<const char*>(NULL),
is_reference_error);
}
void ReportUnexpectedToken(Token::Value token);
@ -743,9 +746,9 @@ class PreParserScope {
class PreParserFactory {
public:
explicit PreParserFactory(void* extra_param) {}
PreParserExpression NewLiteral(PreParserIdentifier identifier,
int pos) {
explicit PreParserFactory(void* extra_param1, void* extra_param2) {}
PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewNumberLiteral(double number,
@ -997,8 +1000,8 @@ class PreParserTraits {
// Producing data during the recursive descent.
PreParserIdentifier GetSymbol(Scanner* scanner);
static PreParserIdentifier NextLiteralString(Scanner* scanner,
PretenureFlag tenured) {
static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
return PreParserIdentifier::Default();
}
@ -1184,7 +1187,8 @@ ParserBase<Traits>::FunctionState::FunctionState(
FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope,
typename Traits::Type::Zone* extra_param)
typename Traits::Type::Zone* extra_param,
AstValueFactory* ast_value_factory)
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
next_handler_index_(0),
expected_property_count_(0),
@ -1196,7 +1200,7 @@ ParserBase<Traits>::FunctionState::FunctionState(
outer_scope_(*scope_stack),
saved_ast_node_id_(0),
extra_param_(extra_param),
factory_(extra_param) {
factory_(extra_param, ast_value_factory) {
*scope_stack_ = scope;
*function_state_stack = this;
Traits::SetUpFunctionState(this, extra_param);
@ -1322,14 +1326,14 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
int literal_index = function_state_->NextMaterializedLiteralIndex();
IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
IdentifierT js_pattern = this->GetNextSymbol(scanner());
if (!scanner()->ScanRegExpFlags()) {
Next();
ReportMessage("invalid_regexp_flags");
*ok = false;
return Traits::EmptyExpression();
}
IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
IdentifierT js_flags = this->GetNextSymbol(scanner());
Next();
return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
}
@ -1574,7 +1578,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
}
// Failed to parse as get/set property, so it's just a normal property
// (which might be called "get" or "set" or something else).
key = factory()->NewLiteral(id, next_pos);
key = factory()->NewStringLiteral(id, next_pos);
break;
}
case Token::STRING: {
@ -1586,7 +1590,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
key = factory()->NewNumberLiteral(index, next_pos);
break;
}
key = factory()->NewLiteral(string, next_pos);
key = factory()->NewStringLiteral(string, next_pos);
break;
}
case Token::NUMBER: {
@ -1599,7 +1603,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
if (Token::IsKeyword(next)) {
Consume(next);
IdentifierT string = this->GetSymbol(scanner_);
key = factory()->NewLiteral(string, next_pos);
key = factory()->NewStringLiteral(string, next_pos);
} else {
Token::Value next = Next();
ReportUnexpectedToken(next);
@ -1968,7 +1972,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK);
result = factory()->NewProperty(
result, factory()->NewLiteral(name, pos), pos);
result, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) this->PushLiteralName(fni_, name);
break;
}
@ -2090,7 +2094,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK);
expression = factory()->NewProperty(
expression, factory()->NewLiteral(name, pos), pos);
expression, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) {
this->PushLiteralName(fni_, name);
}

View File

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

View File

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

View File

@ -20,7 +20,9 @@ class Processor: public AstVisitor {
result_assigned_(false),
is_set_(false),
in_try_(false),
factory_(zone) {
// Passing a null AstValueFactory is fine, because Processor doesn't
// need to create strings or literals.
factory_(zone, NULL) {
InitializeAstVisitor(zone);
}
@ -234,8 +236,10 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
ZoneList<Statement*>* body = function->body();
if (!body->is_empty()) {
Variable* result = scope->NewTemporary(
info->isolate()->factory()->dot_result_string());
Variable* result =
scope->NewTemporary(info->ast_value_factory()->dot_result_string());
// The name string must be internalized at this point.
ASSERT(!result->name().is_null());
Processor processor(result, info->zone());
processor.Process(body);
if (processor.HasStackOverflow()) return false;
@ -250,7 +254,7 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
// coincides with the end of the with scope which is the position of '1'.
int pos = function->end_position();
VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
result->name(), false, result->interface(), pos);
result->raw_name(), false, result->interface(), pos);
result_proxy->BindTo(result);
Statement* result_statement =
processor.factory()->NewReturnStatement(result_proxy, pos);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,6 +31,7 @@
#include "src/v8.h"
#include "src/ast-value-factory.h"
#include "src/compiler.h"
#include "src/execution.h"
#include "src/isolate.h"
@ -796,8 +797,10 @@ void TestScanRegExp(const char* re_source, const char* expected) {
CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
scanner.Next(); // Current token is now the regexp literal.
i::AstValueFactory ast_value_factory(NULL);
ast_value_factory.Internalize(CcTest::i_isolate());
i::Handle<i::String> val =
scanner.AllocateInternalizedString(CcTest::i_isolate());
scanner.CurrentSymbol(&ast_value_factory)->string();
i::DisallowHeapAllocation no_alloc;
i::String::FlatContent content = val->GetFlatContent();
CHECK(content.IsAscii());

View File

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

View File

@ -44,6 +44,18 @@
using namespace v8::internal;
class StringResource8 : public v8::String::ExternalAsciiStringResource {
public:
StringResource8(const char* data, int length)
: data_(data), length_(length) { }
virtual size_t length() const { return length_; }
virtual const char* data() const { return data_; }
private:
const char* data_;
int length_;
};
std::pair<TimeDelta, TimeDelta> RunBaselineParser(
const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate,
v8::Handle<v8::Context> context) {
@ -63,7 +75,9 @@ std::pair<TimeDelta, TimeDelta> RunBaselineParser(
break;
}
case LATIN1: {
source_handle = v8::String::NewFromOneByte(isolate, source);
StringResource8* string_resource =
new StringResource8(reinterpret_cast<const char*>(source), length);
source_handle = v8::String::NewExternal(isolate, string_resource);
break;
}
}