Add "own" symbols support.

"Own" symbols are symbols that can only denote own properties of
objects.

R=hpayer@chromium.org, verwaest@chromium.org

Committed: https://code.google.com/p/v8/source/detail?r=23056

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23083 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dslomov@chromium.org 2014-08-12 15:28:20 +00:00
parent 0f81d7698a
commit d2fe3e68ea
13 changed files with 121 additions and 7 deletions

View File

@ -664,6 +664,14 @@ Handle<Symbol> Factory::NewPrivateSymbol() {
}
Handle<Symbol> Factory::NewPrivateOwnSymbol() {
Handle<Symbol> symbol = NewSymbol();
symbol->set_is_private(true);
symbol->set_is_own(true);
return symbol;
}
Handle<Context> Factory::NewNativeContext() {
Handle<FixedArray> array = NewFixedArray(Context::NATIVE_CONTEXT_SLOTS);
array->set_map_no_write_barrier(*native_context_map());

View File

@ -221,6 +221,7 @@ class Factory V8_FINAL {
// Create a symbol.
Handle<Symbol> NewSymbol();
Handle<Symbol> NewPrivateSymbol();
Handle<Symbol> NewPrivateOwnSymbol();
// Create a global (but otherwise uninitialized) context.
Handle<Context> NewNativeContext();

View File

@ -2834,7 +2834,7 @@ void Heap::CreateInitialObjects() {
// Allocate the dictionary of intrinsic function names.
Handle<NameDictionary> intrinsic_names =
NameDictionary::New(isolate(), Runtime::kNumFunctions);
NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED);
Runtime::InitializeIntrinsicFunctionNames(isolate(), intrinsic_names);
set_intrinsic_function_names(*intrinsic_names);

View File

@ -47,7 +47,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
LookupIterator(Handle<Object> receiver,
Handle<Name> name,
Configuration configuration = CHECK_ALL)
: configuration_(configuration),
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
property_kind_(DATA),
property_encoding_(DESCRIPTOR),
@ -66,7 +66,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
Handle<Name> name,
Handle<JSReceiver> holder,
Configuration configuration = CHECK_ALL)
: configuration_(configuration),
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
property_kind_(DATA),
property_encoding_(DESCRIPTOR),
@ -187,6 +187,15 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
return number_;
}
static Configuration ComputeConfiguration(
Configuration configuration, Handle<Name> name) {
if (name->IsOwn()) {
return static_cast<Configuration>(configuration & CHECK_OWN);
} else {
return configuration;
}
}
Configuration configuration_;
State state_;
bool has_property_;

View File

@ -3372,6 +3372,7 @@ bool Name::Equals(Handle<Name> one, Handle<Name> two) {
ACCESSORS(Symbol, name, Object, kNameOffset)
ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
BOOL_ACCESSORS(Symbol, flags, is_own, kOwnBit)
bool String::Equals(String* other) {
@ -6496,6 +6497,10 @@ uint32_t Name::Hash() {
return String::cast(this)->ComputeAndSetHash();
}
bool Name::IsOwn() {
return this->IsSymbol() && Symbol::cast(this)->is_own();
}
StringHasher::StringHasher(int length, uint32_t seed)
: length_(length),

View File

@ -430,7 +430,8 @@ void Symbol::SymbolPrint(OStream& os) { // NOLINT
HeapObject::PrintHeader(os, "Symbol");
os << " - hash: " << Hash();
os << "\n - name: " << Brief(name());
os << " - private: " << is_private();
os << "\n - private: " << is_private();
os << "\n - own: " << is_own();
os << "\n";
}

View File

@ -3560,6 +3560,11 @@ void JSObject::LookupRealNamedProperty(Handle<Name> name,
void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
LookupResult* result) {
if (name->IsOwn()) {
result->NotFound();
return;
}
DisallowHeapAllocation no_gc;
Isolate* isolate = GetIsolate();
for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) {
@ -6107,7 +6112,7 @@ void JSReceiver::LookupOwn(
}
js_object->LookupOwnRealNamedProperty(name, result);
if (result->IsFound() || !search_hidden_prototypes) return;
if (result->IsFound() || name->IsOwn() || !search_hidden_prototypes) return;
PrototypeIterator iter(GetIsolate(), js_object);
if (!iter.GetCurrent()->IsJSReceiver()) return;
@ -6126,6 +6131,10 @@ void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) {
!iter.IsAtEnd(); iter.Advance()) {
JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result, false);
if (result->IsFound()) return;
if (name->IsOwn()) {
result->NotFound();
return;
}
}
result->NotFound();
}

View File

@ -8954,6 +8954,9 @@ class Name: public HeapObject {
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
// Whether name can only name own properties.
inline bool IsOwn();
DECLARE_CAST(Name)
DECLARE_PRINTER(Name)
@ -9029,6 +9032,10 @@ class Symbol: public Name {
// [is_private]: whether this is a private symbol.
DECL_BOOLEAN_ACCESSORS(is_private)
// [is_own]: whether this is an own symbol, that is, only used to designate
// own properties of objects.
DECL_BOOLEAN_ACCESSORS(is_own)
DECLARE_CAST(Symbol)
// Dispatched behavior.
@ -9044,6 +9051,7 @@ class Symbol: public Name {
private:
static const int kPrivateBit = 0;
static const int kOwnBit = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
};

View File

@ -608,6 +608,17 @@ RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol) {
}
RUNTIME_FUNCTION(Runtime_CreatePrivateOwnSymbol) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
Handle<Symbol> symbol = isolate->factory()->NewPrivateOwnSymbol();
if (name->IsString()) symbol->set_name(*name);
return *symbol;
}
RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);

View File

@ -260,6 +260,7 @@ namespace internal {
F(CreateSymbol, 1, 1) \
F(CreatePrivateSymbol, 1, 1) \
F(CreateGlobalPrivateSymbol, 1, 1) \
F(CreatePrivateOwnSymbol, 1, 1) \
F(NewSymbolWrapper, 1, 1) \
F(SymbolDescription, 1, 1) \
F(SymbolRegistry, 0, 1) \

View File

@ -0,0 +1,55 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
var s = %CreatePrivateOwnSymbol("s");
var s1 = %CreatePrivateOwnSymbol("s1");
function TestSimple() {
var p = {}
p[s] = "moo";
var o = Object.create(p);
assertEquals(undefined, o[s]);
assertEquals("moo", p[s]);
o[s] = "bow-wow";
assertEquals("bow-wow", o[s]);
assertEquals("moo", p[s]);
}
TestSimple();
function TestICs() {
var p = {}
p[s] = "moo";
var o = Object.create(p);
o[s1] = "bow-wow";
function checkNonOwn(o) {
assertEquals(undefined, o[s]);
assertEquals("bow-wow", o[s1]);
}
checkNonOwn(o);
// Test monomorphic/optimized.
for (var i = 0; i < 1000; i++) {
checkNonOwn(o);
}
// Test non-monomorphic.
for (var i = 0; i < 1000; i++) {
var oNew = Object.create(p);
oNew["s" + i] = i;
oNew[s1] = "bow-wow";
checkNonOwn(oNew);
}
}
TestICs();

View File

@ -0,0 +1,5 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony --harmony-proxies
var arg0 = "foo";
%CreatePrivateOwnSymbol(arg0);

View File

@ -47,8 +47,8 @@ EXPAND_MACROS = [
# that the parser doesn't bit-rot. Change the values as needed when you add,
# remove or change runtime functions, but make sure we don't lose our ability
# to parse them!
EXPECTED_FUNCTION_COUNT = 428
EXPECTED_FUZZABLE_COUNT = 331
EXPECTED_FUNCTION_COUNT = 429
EXPECTED_FUZZABLE_COUNT = 332
EXPECTED_CCTEST_COUNT = 7
EXPECTED_UNKNOWN_COUNT = 16
EXPECTED_BUILTINS_COUNT = 808
@ -226,6 +226,7 @@ CUSTOM_KNOWN_GOOD_INPUT = {
"CreateBreakIterator": ["'en-US'", "{type: 'string'}", None, None],
"CreateJSFunctionProxy": [None, "function() {}", None, None, None],
"CreatePrivateSymbol": ["\"foo\"", None],
"CreatePrivateOwnSymbol": ["\"foo\"", None],
"CreateSymbol": ["\"foo\"", None],
"DateParseString": [None, "new Array(8)", None],
"DefineAccessorPropertyUnchecked": [None, None, "function() {}",