Commit d094d0fb authored by verwaest@chromium.org's avatar verwaest@chromium.org

Tag all prototypes as proto, except those set using __proto__

BUG=
R=ishell@chromium.org, yangguo@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23042 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9de44924
......@@ -3204,8 +3204,8 @@ bool v8::Object::SetPrototype(Handle<Value> value) {
// to propagate outside.
TryCatch try_catch;
EXCEPTION_PREAMBLE(isolate);
i::MaybeHandle<i::Object> result = i::JSObject::SetPrototype(
self, value_obj);
i::MaybeHandle<i::Object> result =
i::JSObject::SetPrototype(self, value_obj, false);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, false);
return true;
......
......@@ -68,7 +68,7 @@ function InstantiateFunction(data, name) {
// internal ToBoolean doesn't handle that!
if (typeof parent !== 'undefined') {
var parent_fun = Instantiate(parent);
%SetPrototype(prototype, parent_fun.prototype);
%InternalSetPrototype(prototype, parent_fun.prototype);
}
}
var fun = %CreateApiFunction(data, prototype);
......
......@@ -480,7 +480,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
Handle<JSFunction> object_fun = factory->NewFunction(object_name);
Handle<Map> object_function_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
JSFunction::SetInitialMap(object_fun, object_function_map);
JSFunction::SetInitialMap(object_fun, object_function_map,
isolate->factory()->null_value());
object_function_map->set_unused_property_fields(
JSObject::kInitialGlobalObjectUnusedPropertiesCount);
......@@ -490,6 +491,9 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
Handle<JSObject> prototype = factory->NewJSObject(
isolate->object_function(),
TENURED);
Handle<Map> map = Map::Copy(handle(prototype->map()));
map->set_is_prototype_map(true);
prototype->set_map(*map);
native_context()->set_initial_object_prototype(*prototype);
// For bootstrapping set the array prototype to be the same as the object
......@@ -507,6 +511,15 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
Handle<JSFunction> empty_function = factory->NewFunctionWithoutPrototype(
empty_string, code);
// Allocate the function map first and then patch the prototype later
Handle<Map> empty_function_map =
CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE);
DCHECK(!empty_function_map->is_dictionary_map());
empty_function_map->set_prototype(
native_context()->object_function()->prototype());
empty_function_map->set_is_prototype_map(true);
empty_function->set_map(*empty_function_map);
// --- E m p t y ---
Handle<String> source = factory->NewStringFromStaticAscii("() {}");
Handle<Script> script = factory->NewScript(source);
......@@ -521,13 +534,6 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
native_context()->sloppy_function_without_prototype_map()->
set_prototype(*empty_function);
sloppy_function_map_writable_prototype_->set_prototype(*empty_function);
// Allocate the function map first and then patch the prototype later
Handle<Map> empty_function_map =
CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE);
empty_function_map->set_prototype(
native_context()->object_function()->prototype());
empty_function->set_map(*empty_function_map);
return empty_function;
}
......@@ -1082,6 +1088,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
proto->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
Smi::FromInt(0),
SKIP_WRITE_BARRIER); // It's a Smi.
proto_map->set_is_prototype_map(true);
initial_map->set_prototype(*proto);
factory->SetRegExpIrregexpData(Handle<JSRegExp>::cast(proto),
JSRegExp::IRREGEXP, factory->empty_string(),
......@@ -1204,13 +1211,13 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
}
map->set_function_with_prototype(true);
map->set_prototype(native_context()->object_function()->prototype());
map->set_pre_allocated_property_fields(2);
map->set_inobject_properties(2);
native_context()->set_sloppy_arguments_map(*map);
DCHECK(!function->has_initial_map());
JSFunction::SetInitialMap(function, map);
JSFunction::SetInitialMap(function, map,
isolate->initial_object_prototype());
DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex);
DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
......@@ -1334,7 +1341,8 @@ void Genesis::InstallTypedArray(
JS_TYPED_ARRAY_TYPE,
JSTypedArray::kSizeWithInternalFields,
elements_kind);
JSFunction::SetInitialMap(result, initial_map);
JSFunction::SetInitialMap(result, initial_map,
handle(initial_map->prototype(), isolate()));
*fun = result;
ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
......@@ -1652,7 +1660,7 @@ Handle<JSFunction> Genesis::InstallInternalArray(
Handle<Map> original_map(array_function->initial_map());
Handle<Map> initial_map = Map::Copy(original_map);
initial_map->set_elements_kind(elements_kind);
JSFunction::SetInitialMap(array_function, initial_map);
JSFunction::SetInitialMap(array_function, initial_map, prototype);
// Make "length" magic on instances.
Map::EnsureDescriptorSlack(initial_map, 1);
......
......@@ -1289,8 +1289,8 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
prototype = NewFunctionPrototype(function);
}
initial_map->set_prototype(*prototype);
JSFunction::SetInitialMap(function, initial_map);
JSFunction::SetInitialMap(function, initial_map,
Handle<JSReceiver>::cast(prototype));
return function;
}
......@@ -1321,6 +1321,7 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
new_map = handle(object_function->initial_map());
}
DCHECK(!new_map->is_prototype_map());
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
if (!function->shared()->is_generator()) {
......
......@@ -67,11 +67,11 @@ function SetUpGenerators() {
GeneratorObjectIterator, DONT_ENUM | DONT_DELETE | READ_ONLY);
%AddNamedProperty(GeneratorObjectPrototype, "constructor",
GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetPrototype(GeneratorFunctionPrototype, $Function.prototype);
%InternalSetPrototype(GeneratorFunctionPrototype, $Function.prototype);
%SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor);
%AddNamedProperty(GeneratorFunctionPrototype, "constructor",
GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetPrototype(GeneratorFunction, $Function);
%InternalSetPrototype(GeneratorFunction, $Function);
%SetCode(GeneratorFunction, GeneratorFunctionConstructor);
}
......
......@@ -372,7 +372,7 @@ function MathLog1p(x) {
function SetUpMath() {
%CheckIsBootstrapping();
%SetPrototype($Math, $Object.prototype);
%InternalSetPrototype($Math, $Object.prototype);
%AddNamedProperty(global, "Math", $Math, DONT_ENUM);
%FunctionSetInstanceClassName(MathConstructor, 'Math');
......
......@@ -308,9 +308,9 @@ void Map::MapVerify() {
}
void Map::SharedMapVerify() {
void Map::DictionaryMapVerify() {
MapVerify();
CHECK(is_shared());
CHECK(is_dictionary_map());
CHECK(instance_descriptors()->IsEmpty());
CHECK_EQ(0, pre_allocated_property_fields());
CHECK_EQ(0, unused_property_fields());
......@@ -1012,7 +1012,7 @@ void NormalizedMapCache::NormalizedMapCacheVerify() {
for (int i = 0; i < length(); i++) {
Object* e = FixedArray::get(i);
if (e->IsMap()) {
Map::cast(e)->SharedMapVerify();
Map::cast(e)->DictionaryMapVerify();
} else {
CHECK(e->IsUndefined());
}
......
......@@ -2206,7 +2206,8 @@ void FixedArray::set(int index, Smi* value) {
void FixedArray::set(int index, Object* value) {
DCHECK(map() != GetHeap()->fixed_cow_array_map());
DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
DCHECK_EQ(FIXED_ARRAY_TYPE, map()->instance_type());
DCHECK(index >= 0 && index < this->length());
int offset = kHeaderSize + index * kPointerSize;
WRITE_FIELD(this, offset, value);
......@@ -4460,15 +4461,6 @@ bool Map::is_prototype_map() {
}
void Map::set_is_shared(bool value) {
set_bit_field3(IsShared::update(bit_field3(), value));
}
bool Map::is_shared() {
return IsShared::decode(bit_field3()); }
void Map::set_dictionary_map(bool value) {
uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value);
new_bit_field3 = IsUnstable::update(new_bit_field3, value);
......@@ -4486,8 +4478,8 @@ Code::Flags Code::flags() {
}
void Map::set_owns_descriptors(bool is_shared) {
set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
void Map::set_owns_descriptors(bool owns_descriptors) {
set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors));
}
......
This diff is collapsed.
......@@ -247,12 +247,12 @@ enum PropertyNormalizationMode {
};
// NormalizedMapSharingMode is used to specify whether a map may be shared
// by different objects with normalized properties.
enum NormalizedMapSharingMode {
UNIQUE_NORMALIZED_MAP,
SHARED_NORMALIZED_MAP
};
// Indicates how aggressively the prototype should be optimized. FAST_PROTOTYPE
// will give the fastest result by tailoring the map to the prototype, but that
// will cause polymorphism with other objects. REGULAR_PROTOTYPE is to be used
// (at least for now) when dynamically modifying the prototype chain of an
// object using __proto__ or Object.setPrototypeOf.
enum PrototypeOptimizationMode { REGULAR_PROTOTYPE, FAST_PROTOTYPE };
// Indicates whether transitions can be added to a source map or not.
......@@ -2196,7 +2196,8 @@ class JSObject: public JSReceiver {
Handle<Object> value,
PropertyDetails details);
static void OptimizeAsPrototype(Handle<JSObject> object);
static void OptimizeAsPrototype(Handle<JSObject> object,
PrototypeOptimizationMode mode);
static void ReoptimizeIfPrototype(Handle<JSObject> object);
// Retrieve interceptors.
......@@ -2475,9 +2476,7 @@ class JSObject: public JSReceiver {
// Set the object's prototype (only JSReceiver and null are allowed values).
MUST_USE_RESULT static MaybeHandle<Object> SetPrototype(
Handle<JSObject> object,
Handle<Object> value,
bool skip_hidden_prototypes = false);
Handle<JSObject> object, Handle<Object> value, bool from_javascript);
// Initializes the body after properties slot, properties slot is
// initialized by set_properties. Fill the pre-allocated fields with
......@@ -6125,15 +6124,16 @@ class Map: public HeapObject {
class NumberOfOwnDescriptorsBits: public BitField<int,
kDescriptorIndexBitCount, kDescriptorIndexBitCount> {}; // NOLINT
STATIC_ASSERT(kDescriptorIndexBitCount + kDescriptorIndexBitCount == 20);
class IsShared: public BitField<bool, 20, 1> {};
class DictionaryMap: public BitField<bool, 21, 1> {};
class OwnsDescriptors: public BitField<bool, 22, 1> {};
class HasInstanceCallHandler: public BitField<bool, 23, 1> {};
class Deprecated: public BitField<bool, 24, 1> {};
class IsFrozen: public BitField<bool, 25, 1> {};
class IsUnstable: public BitField<bool, 26, 1> {};
class IsMigrationTarget: public BitField<bool, 27, 1> {};
class DoneInobjectSlackTracking: public BitField<bool, 28, 1> {};
class DictionaryMap : public BitField<bool, 20, 1> {};
class OwnsDescriptors : public BitField<bool, 21, 1> {};
class HasInstanceCallHandler : public BitField<bool, 22, 1> {};
class Deprecated : public BitField<bool, 23, 1> {};
class IsFrozen : public BitField<bool, 24, 1> {};
class IsUnstable : public BitField<bool, 25, 1> {};
class IsMigrationTarget : public BitField<bool, 26, 1> {};
class DoneInobjectSlackTracking : public BitField<bool, 27, 1> {};
// Bit 28 is free.
// Keep this bit field at the very end for better code in
// Builtins::kJSConstructStubGeneric stub.
class ConstructionCount: public BitField<int, 29, 3> {};
......@@ -6335,12 +6335,6 @@ class Map: public HeapObject {
// function that was used to instantiate the object).
String* constructor_name();
// Tells whether the map is shared between objects that may have different
// behavior. If true, the map should never be modified, instead a clone
// should be created and modified.
inline void set_is_shared(bool value);
inline bool is_shared();
// Tells whether the map is used for JSObjects in dictionary mode (ie
// normalized objects, ie objects for which HasFastProperties returns false).
// A map can never be used for both dictionary mode and fast mode JSObjects.
......@@ -6460,7 +6454,7 @@ class Map: public HeapObject {
}
inline bool owns_descriptors();
inline void set_owns_descriptors(bool is_shared);
inline void set_owns_descriptors(bool owns_descriptors);
inline bool has_instance_call_handler();
inline void set_has_instance_call_handler();
inline void freeze();
......@@ -6649,7 +6643,7 @@ class Map: public HeapObject {
DECLARE_VERIFIER(Map)
#ifdef VERIFY_HEAP
void SharedMapVerify();
void DictionaryMapVerify();
void VerifyOmittedMapChecks();
#endif
......@@ -6795,8 +6789,7 @@ class Map: public HeapObject {
TransitionFlag flag);
static Handle<Map> CopyNormalized(Handle<Map> map,
PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
PropertyNormalizationMode mode);
// Fires when the layout of an object with a leaf map changes.
// This includes adding transitions to the leaf map or changing
......@@ -7780,7 +7773,8 @@ class JSFunction: public JSObject {
// The initial map for an object created by this constructor.
inline Map* initial_map();
static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map);
static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
Handle<Object> prototype);
inline bool has_initial_map();
static void EnsureHasInitialMap(Handle<JSFunction> function);
......
......@@ -1862,6 +1862,20 @@ static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
}
RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
DCHECK(!obj->IsAccessCheckNeeded());
DCHECK(!obj->map()->is_observed());
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, JSObject::SetPrototype(obj, prototype, false));
return *result;
}
RUNTIME_FUNCTION(Runtime_SetPrototype) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
......
......@@ -46,6 +46,7 @@ namespace internal {
\
F(GetPrototype, 1, 1) \
F(SetPrototype, 2, 1) \
F(InternalSetPrototype, 2, 1) \
F(IsInPrototypeChain, 2, 1) \
\
F(GetOwnProperty, 2, 1) \
......
......@@ -1338,6 +1338,7 @@ void StartupSerializer::SerializeObject(
int skip) {
CHECK(o->IsHeapObject());
HeapObject* heap_object = HeapObject::cast(o);
DCHECK(!heap_object->IsJSFunction());
int root_index;
if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
......
......@@ -349,7 +349,7 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
CompareNilICStub* stub) {
Isolate* isolate = receiver_map->GetIsolate();
Handle<String> name(isolate->heap()->empty_string());
if (!receiver_map->is_shared()) {
if (!receiver_map->is_dictionary_map()) {
Handle<Code> cached_ic =
Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState());
if (!cached_ic.is_null()) return cached_ic;
......@@ -359,7 +359,7 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
pattern.Add(isolate->factory()->meta_map(), receiver_map);
Handle<Code> ic = stub->GetCodeCopy(pattern);
if (!receiver_map->is_shared()) {
if (!receiver_map->is_dictionary_map()) {
Map::UpdateCodeCache(receiver_map, name, ic);
}
......
......@@ -96,7 +96,7 @@ function SetUpLockedPrototype(constructor, fields, methods) {
%AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetNativeFlag(f);
}
%SetPrototype(prototype, null);
%InternalSetPrototype(prototype, null);
%ToFastProperties(prototype);
}
......@@ -1125,7 +1125,8 @@ function ObjectCreate(proto, properties) {
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
throw MakeTypeError("proto_object_or_null", [proto]);
}
var obj = { __proto__: proto };
var obj = {};
%InternalSetPrototype(obj, proto);
if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
return obj;
}
......
// 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 _obj = new Object();
var _prototype = new Object();
%InternalSetPrototype(_obj, _prototype);
......@@ -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 = 427
EXPECTED_FUZZABLE_COUNT = 330
EXPECTED_FUNCTION_COUNT = 428
EXPECTED_FUZZABLE_COUNT = 331
EXPECTED_CCTEST_COUNT = 7
EXPECTED_UNKNOWN_COUNT = 16
EXPECTED_BUILTINS_COUNT = 809
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment