Commit e35a0327 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

Port ObjectGetOwnPropertyDescriptor to CSA

Bug: 
Change-Id: I7cb8ace4183c0dcf34d71d1b378204383c17ba56
Reviewed-on: https://chromium-review.googlesource.com/678718Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Maya Lekova <mslekova@google.com>
Cr-Commit-Position: refs/heads/master@{#48133}
parent 62960a03
......@@ -1808,6 +1808,8 @@ v8_source_set("v8_base") {
"src/objects/name.h",
"src/objects/object-macros-undef.h",
"src/objects/object-macros.h",
"src/objects/property-descriptor-object-inl.h",
"src/objects/property-descriptor-object.h",
"src/objects/regexp-match-info.h",
"src/objects/scope-info.cc",
"src/objects/scope-info.h",
......
......@@ -706,7 +706,8 @@ namespace internal {
CPP(ObjectDefineSetter) \
CPP(ObjectEntries) \
CPP(ObjectFreeze) \
CPP(ObjectGetOwnPropertyDescriptor) \
TFJ(ObjectGetOwnPropertyDescriptor, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
CPP(ObjectGetOwnPropertyDescriptors) \
CPP(ObjectGetOwnPropertyNames) \
CPP(ObjectGetOwnPropertySymbols) \
......
......@@ -6,6 +6,7 @@
#include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h"
#include "src/factory-inl.h"
#include "src/objects/property-descriptor-object.h"
#include "src/objects/shared-function-info.h"
namespace v8 {
......@@ -23,6 +24,9 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler {
protected:
void ReturnToStringFormat(Node* context, Node* string);
void AddToDictionaryIf(Node* condition, Node* name_dictionary,
Handle<Name> name, Node* value, Label* bailout);
Node* FromPropertyDescriptor(Node* context, Node* desc);
};
void ObjectBuiltinsAssembler::ReturnToStringFormat(Node* context,
......@@ -689,5 +693,181 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
}
}
// ES6 section 19.1.2.7 Object.getOwnPropertyDescriptor ( O, P )
TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
Node* context = Parameter(BuiltinDescriptor::kContext);
CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
UndefinedConstant()));
CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
Node* obj = args.GetOptionalArgumentValue(0);
Node* key = args.GetOptionalArgumentValue(1);
// 1. Let obj be ? ToObject(O).
Node* object = CallBuiltin(Builtins::kToObject, context, obj);
// 2. Let key be ? ToPropertyKey(P).
Node* name = ToName(context, key);
// 3. Let desc be ? obj.[[GetOwnProperty]](key).
Node* desc =
CallRuntime(Runtime::kGetOwnPropertyDescriptor, context, object, name);
Label return_undefined(this, Label::kDeferred);
GotoIf(IsUndefined(desc), &return_undefined);
CSA_ASSERT(this, IsFixedArray(desc));
// 4. Return FromPropertyDescriptor(desc).
args.PopAndReturn(FromPropertyDescriptor(context, desc));
BIND(&return_undefined);
args.PopAndReturn(UndefinedConstant());
}
void ObjectBuiltinsAssembler::AddToDictionaryIf(Node* condition,
Node* name_dictionary,
Handle<Name> name, Node* value,
Label* bailout) {
Label done(this);
GotoIfNot(condition, &done);
Add<NameDictionary>(name_dictionary, HeapConstant(name), value, bailout);
Goto(&done);
BIND(&done);
}
Node* ObjectBuiltinsAssembler::FromPropertyDescriptor(Node* context,
Node* desc) {
VARIABLE(js_descriptor, MachineRepresentation::kTagged);
Node* flags = LoadAndUntagToWord32ObjectField(
desc, PropertyDescriptorObject::kFlagsOffset);
Node* has_flags =
Word32And(flags, Int32Constant(PropertyDescriptorObject::kHasMask));
Label if_accessor_desc(this), if_data_desc(this), if_generic_desc(this),
return_desc(this);
GotoIf(
Word32Equal(has_flags,
Int32Constant(
PropertyDescriptorObject::kRegularAccessorPropertyBits)),
&if_accessor_desc);
GotoIf(Word32Equal(
has_flags,
Int32Constant(PropertyDescriptorObject::kRegularDataPropertyBits)),
&if_data_desc);
Goto(&if_generic_desc);
BIND(&if_accessor_desc);
{
Node* native_context = LoadNativeContext(context);
Node* map = LoadContextElement(
native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX);
Node* js_desc = AllocateJSObjectFromMap(map);
StoreObjectFieldNoWriteBarrier(
js_desc, JSAccessorPropertyDescriptor::kGetOffset,
LoadObjectField(desc, PropertyDescriptorObject::kGetOffset));
StoreObjectFieldNoWriteBarrier(
js_desc, JSAccessorPropertyDescriptor::kSetOffset,
LoadObjectField(desc, PropertyDescriptorObject::kSetOffset));
StoreObjectFieldNoWriteBarrier(
js_desc, JSAccessorPropertyDescriptor::kEnumerableOffset,
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)));
StoreObjectFieldNoWriteBarrier(
js_desc, JSAccessorPropertyDescriptor::kConfigurableOffset,
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
js_descriptor.Bind(js_desc);
Goto(&return_desc);
}
BIND(&if_data_desc);
{
Node* native_context = LoadNativeContext(context);
Node* map = LoadContextElement(native_context,
Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX);
Node* js_desc = AllocateJSObjectFromMap(map);
StoreObjectFieldNoWriteBarrier(
js_desc, JSDataPropertyDescriptor::kValueOffset,
LoadObjectField(desc, PropertyDescriptorObject::kValueOffset));
StoreObjectFieldNoWriteBarrier(
js_desc, JSDataPropertyDescriptor::kWritableOffset,
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)));
StoreObjectFieldNoWriteBarrier(
js_desc, JSDataPropertyDescriptor::kEnumerableOffset,
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)));
StoreObjectFieldNoWriteBarrier(
js_desc, JSDataPropertyDescriptor::kConfigurableOffset,
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
js_descriptor.Bind(js_desc);
Goto(&return_desc);
}
BIND(&if_generic_desc);
{
Node* native_context = LoadNativeContext(context);
Node* map = LoadContextElement(
native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP);
// We want to preallocate the slots for value, writable, get, set,
// enumerable and configurable - a total of 6
Node* properties = AllocateNameDictionary(6);
Node* js_desc = AllocateJSObjectFromMap(map, properties);
Label bailout(this, Label::kDeferred);
Factory* factory = isolate()->factory();
Node* value = LoadObjectField(desc, PropertyDescriptorObject::kValueOffset);
AddToDictionaryIf(IsNotTheHole(value), properties, factory->value_string(),
value, &bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags),
properties, factory->writable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)),
&bailout);
Node* get = LoadObjectField(desc, PropertyDescriptorObject::kGetOffset);
AddToDictionaryIf(IsNotTheHole(get), properties, factory->get_string(), get,
&bailout);
Node* set = LoadObjectField(desc, PropertyDescriptorObject::kSetOffset);
AddToDictionaryIf(IsNotTheHole(set), properties, factory->set_string(), set,
&bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags),
properties, factory->enumerable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)),
&bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasConfigurableBit>(flags),
properties, factory->configurable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)),
&bailout);
js_descriptor.Bind(js_desc);
Goto(&return_desc);
BIND(&bailout);
CSA_ASSERT(this, Int32Constant(0));
Unreachable();
}
BIND(&return_desc);
return js_descriptor.value();
}
} // namespace internal
} // namespace v8
......@@ -340,29 +340,6 @@ BUILTIN(ObjectPrototypeSetProto) {
return isolate->heap()->undefined_value();
}
// ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
BUILTIN(ObjectGetOwnPropertyDescriptor) {
HandleScope scope(isolate);
// 1. Let obj be ? ToObject(O).
Handle<Object> object = args.atOrUndefined(isolate, 1);
Handle<JSReceiver> receiver;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Object::ToObject(isolate, object));
// 2. Let key be ? ToPropertyKey(P).
Handle<Object> property = args.atOrUndefined(isolate, 2);
Handle<Name> key;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
Object::ToName(isolate, property));
// 3. Let desc be ? obj.[[GetOwnProperty]](key).
PropertyDescriptor desc;
Maybe<bool> found =
JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
MAYBE_RETURN(found, isolate->heap()->exception());
// 4. Return FromPropertyDescriptor(desc).
if (!found.FromJust()) return isolate->heap()->undefined_value();
return *desc.ToObject(isolate);
}
namespace {
Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
......
......@@ -365,6 +365,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<BoolT> WordIsWordAligned(SloppyTNode<WordT> word);
TNode<BoolT> WordIsPowerOfTwo(SloppyTNode<IntPtrT> value);
Node* IsNotTheHole(Node* value) { return Word32BinaryNot(IsTheHole(value)); }
#if DEBUG
void Bind(Label* label, AssemblerDebugInfo debug_info);
#else
......
......@@ -324,6 +324,8 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(ThrowInvalidHint) \
V(ThrowNotDateError) \
V(ThrowRangeError) \
V(ToName) \
V(GetOwnPropertyDescriptor) \
/* Misc. */ \
V(Call) \
V(MaxSmi) \
......
......@@ -318,6 +318,8 @@ bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); }
bool HeapObject::IsPropertyDescriptorObject() const { return IsFixedArray(); }
bool HeapObject::IsEnumCache() const { return IsTuple2(); }
bool HeapObject::IsFrameArray() const { return IsFixedArray(); }
......
......@@ -174,6 +174,7 @@ namespace v8 {
namespace internal {
struct InliningPosition;
class PropertyDescriptorObject;
enum KeyedAccessStoreMode {
STANDARD_STORE,
......@@ -1072,6 +1073,7 @@ template <class C> inline bool Is(Object* obj);
V(PreParsedScopeData) \
V(PropertyArray) \
V(PropertyCell) \
V(PropertyDescriptorObject) \
V(RegExpMatchInfo) \
V(ScopeInfo) \
V(ScriptContextTable) \
......
// Copyright 2017 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.
#ifndef V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_INL_H_
#define V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_INL_H_
#include "src/objects-inl.h"
#include "src/objects/property-descriptor-object.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
CAST_ACCESSOR(PropertyDescriptorObject)
}
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_INL_H_
// Copyright 2017 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.
#ifndef V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_H_
#define V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_H_
#include "src/objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class PropertyDescriptorObject : public FixedArray {
public:
#define FLAGS_BIT_FIELDS(V, _) \
V(IsEnumerableBit, bool, 1, _) \
V(HasEnumerableBit, bool, 1, _) \
V(IsConfigurableBit, bool, 1, _) \
V(HasConfigurableBit, bool, 1, _) \
V(IsWritableBit, bool, 1, _) \
V(HasWritableBit, bool, 1, _) \
V(HasValueBit, bool, 1, _) \
V(HasGetBit, bool, 1, _) \
V(HasSetBit, bool, 1, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS
enum { kFlagsIndex, kValueIndex, kGetIndex, kSetIndex, kLength };
DECL_CAST(PropertyDescriptorObject)
static const int kRegularAccessorPropertyBits =
HasEnumerableBit::kMask | HasConfigurableBit::kMask | HasGetBit::kMask |
HasSetBit::kMask;
static const int kRegularDataPropertyBits =
HasEnumerableBit::kMask | HasConfigurableBit::kMask |
HasWritableBit::kMask | HasValueBit::kMask;
static const int kHasMask = HasEnumerableBit::kMask |
HasConfigurableBit::kMask |
HasWritableBit::kMask | HasValueBit::kMask |
HasGetBit::kMask | HasSetBit::kMask;
static const int kValueOffset =
FixedArray::OffsetOfElementAt(PropertyDescriptorObject::kValueIndex);
static const int kFlagsOffset =
FixedArray::OffsetOfElementAt(PropertyDescriptorObject::kFlagsIndex);
static const int kGetOffset =
FixedArray::OffsetOfElementAt(PropertyDescriptorObject::kGetIndex);
static const int kSetOffset =
FixedArray::OffsetOfElementAt(PropertyDescriptorObject::kSetIndex);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_PROPERTY_DESCRIPTOR_OBJECT_H_
......@@ -9,6 +9,7 @@
#include "src/isolate-inl.h"
#include "src/lookup.h"
#include "src/objects-inl.h"
#include "src/objects/property-descriptor-object-inl.h"
namespace v8 {
namespace internal {
......@@ -341,5 +342,33 @@ void PropertyDescriptor::CompletePropertyDescriptor(Isolate* isolate,
// 8. Return Desc.
}
Handle<PropertyDescriptorObject> PropertyDescriptor::ToPropertyDescriptorObject(
Isolate* isolate) {
Handle<PropertyDescriptorObject> obj = Handle<PropertyDescriptorObject>::cast(
isolate->factory()->NewFixedArray(PropertyDescriptorObject::kLength));
int flags =
PropertyDescriptorObject::IsEnumerableBit::encode(enumerable_) |
PropertyDescriptorObject::HasEnumerableBit::encode(has_enumerable_) |
PropertyDescriptorObject::IsConfigurableBit::encode(configurable_) |
PropertyDescriptorObject::HasConfigurableBit::encode(has_configurable_) |
PropertyDescriptorObject::IsWritableBit::encode(writable_) |
PropertyDescriptorObject::HasWritableBit::encode(has_writable_) |
PropertyDescriptorObject::HasValueBit::encode(has_value()) |
PropertyDescriptorObject::HasGetBit::encode(has_get()) |
PropertyDescriptorObject::HasSetBit::encode(has_set());
obj->set(PropertyDescriptorObject::kFlagsIndex, Smi::FromInt(flags));
obj->set(PropertyDescriptorObject::kValueIndex,
has_value() ? *value_ : isolate->heap()->the_hole_value());
obj->set(PropertyDescriptorObject::kGetIndex,
has_get() ? *get_ : isolate->heap()->the_hole_value());
obj->set(PropertyDescriptorObject::kSetIndex,
has_set() ? *set_ : isolate->heap()->the_hole_value());
return obj;
}
} // namespace internal
} // namespace v8
......@@ -15,6 +15,7 @@ namespace internal {
class Isolate;
class Object;
class PropertyDescriptorObject;
class PropertyDescriptor {
public:
......@@ -44,6 +45,8 @@ class PropertyDescriptor {
// ES6 6.2.4.4
Handle<Object> ToObject(Isolate* isolate);
Handle<PropertyDescriptorObject> ToPropertyDescriptorObject(Isolate* isolate);
// ES6 6.2.4.5
static bool ToPropertyDescriptor(Isolate* isolate, Handle<Object> obj,
PropertyDescriptor* desc);
......
......@@ -9,6 +9,7 @@
#include "src/debug/debug.h"
#include "src/isolate-inl.h"
#include "src/messages.h"
#include "src/objects/property-descriptor-object.h"
#include "src/property-descriptor.h"
#include "src/runtime/runtime.h"
......@@ -1200,5 +1201,21 @@ RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) {
return isolate->heap()->ToBoolean(!obj->IterationHasObservableEffects());
}
RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
PropertyDescriptor desc;
Maybe<bool> found =
JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc);
MAYBE_RETURN(found, isolate->heap()->exception());
if (!found.FromJust()) return isolate->heap()->undefined_value();
return *desc.ToPropertyDescriptorObject(isolate);
}
} // namespace internal
} // namespace v8
......@@ -427,7 +427,8 @@ namespace internal {
F(HasInPrototypeChain, 2, 1) \
F(CreateIterResultObject, 2, 1) \
F(CreateDataProperty, 3, 1) \
F(IterableToListCanBeElided, 1, 1)
F(IterableToListCanBeElided, 1, 1) \
F(GetOwnPropertyDescriptor, 2, 1)
#define FOR_EACH_INTRINSIC_OPERATORS(F) \
F(Multiply, 2, 1) \
......
......@@ -1188,6 +1188,8 @@
'objects/module.h',
'objects/object-macros.h',
'objects/object-macros-undef.h',
'objects/property-descriptor-object.h',
'objects/property-descriptor-object-inl.h',
'objects/regexp-match-info.h',
'objects/scope-info.cc',
'objects/scope-info.h',
......
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