| Index: src/compiler/js-builtin-reducer.cc
|
| diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc
|
| index 6698408f94b5778e49a0decd4688215e788e8c07..d782340baf81bdb1fa9dc9afbd1d52bb537f52b6 100644
|
| --- a/src/compiler/js-builtin-reducer.cc
|
| +++ b/src/compiler/js-builtin-reducer.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "src/compiler/js-builtin-reducer.h"
|
|
|
| +#include "src/base/bits.h"
|
| #include "src/compilation-dependencies.h"
|
| #include "src/compiler/access-builder.h"
|
| #include "src/compiler/js-graph.h"
|
| @@ -1485,6 +1486,117 @@ Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) {
|
| return NoChange();
|
| }
|
|
|
| +// ES6 section #sec-object.create Object.create(proto, properties)
|
| +Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
|
| + // We need exactly target, receiver and value parameters.
|
| + int arg_count = node->op()->ValueInputCount();
|
| + if (arg_count != 3) return NoChange();
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
| + Node* prototype = NodeProperties::GetValueInput(node, 2);
|
| + Type* prototype_type = NodeProperties::GetType(prototype);
|
| + Handle<Map> instance_map;
|
| + if (!prototype_type->IsHeapConstant()) return NoChange();
|
| + Handle<HeapObject> prototype_const =
|
| + prototype_type->AsHeapConstant()->Value();
|
| + if (!prototype_const->IsNull(isolate()) && !prototype_const->IsJSReceiver()) {
|
| + return NoChange();
|
| + }
|
| + instance_map = Map::GetObjectCreateMap(prototype_const);
|
| + Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
| + if (instance_map->is_dictionary_map()) {
|
| + // Allocated an empty NameDictionary as backing store for the properties.
|
| + Handle<Map> map(isolate()->heap()->hash_table_map(), isolate());
|
| + int capacity =
|
| + NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
|
| + DCHECK(base::bits::IsPowerOfTwo32(capacity));
|
| + int length = NameDictionary::EntryToIndex(capacity);
|
| + int size = NameDictionary::SizeFor(length);
|
| +
|
| + effect = graph()->NewNode(
|
| + common()->BeginRegion(RegionObservability::kNotObservable), effect);
|
| +
|
| + Node* value = effect =
|
| + graph()->NewNode(simplified()->Allocate(NOT_TENURED),
|
| + jsgraph()->Constant(size), effect, control);
|
| + effect =
|
| + graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
|
| + value, jsgraph()->HeapConstant(map), effect, control);
|
| +
|
| + // Initialize FixedArray fields.
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), value,
|
| + jsgraph()->SmiConstant(length), effect, control);
|
| + // Initialize HashTable fields.
|
| + effect =
|
| + graph()->NewNode(simplified()->StoreField(
|
| + AccessBuilder::ForHashTableBaseNumberOfElements()),
|
| + value, jsgraph()->SmiConstant(0), effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(
|
| + AccessBuilder::ForHashTableBaseNumberOfDeletedElement()),
|
| + value, jsgraph()->SmiConstant(0), effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForHashTableBaseCapacity()),
|
| + value, jsgraph()->SmiConstant(capacity), effect, control);
|
| + // Initialize Dictionary fields.
|
| + Node* undefined = jsgraph()->UndefinedConstant();
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForDictionaryMaxNumberKey()),
|
| + value, undefined, effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(
|
| + AccessBuilder::ForDictionaryNextEnumerationIndex()),
|
| + value, jsgraph()->SmiConstant(PropertyDetails::kInitialIndex), effect,
|
| + control);
|
| + // Initialize hte Properties fields.
|
| + for (int index = NameDictionary::kNextEnumerationIndexIndex + 1;
|
| + index < length; index++) {
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(
|
| + AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier)),
|
| + value, undefined, effect, control);
|
| + }
|
| + properties = effect =
|
| + graph()->NewNode(common()->FinishRegion(), value, effect);
|
| + }
|
| +
|
| + int const instance_size = instance_map->instance_size();
|
| + if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
|
| + dependencies()->AssumeInitialMapCantChange(instance_map);
|
| +
|
| + // Emit code to allocate the JSObject instance for the given
|
| + // {instance_map}.
|
| + effect = graph()->NewNode(
|
| + common()->BeginRegion(RegionObservability::kNotObservable), effect);
|
| + Node* value = effect =
|
| + graph()->NewNode(simplified()->Allocate(NOT_TENURED),
|
| + jsgraph()->Constant(instance_size), effect, control);
|
| + effect =
|
| + graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), value,
|
| + jsgraph()->HeapConstant(instance_map), effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
|
| + properties, effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
|
| + jsgraph()->EmptyFixedArrayConstant(), effect, control);
|
| + // Initialize Object fields.
|
| + Node* undefined = jsgraph()->UndefinedConstant();
|
| + for (int offset = JSObject::kHeaderSize; offset < instance_size;
|
| + offset += kPointerSize) {
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(
|
| + AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier)),
|
| + value, undefined, effect, control);
|
| + }
|
| + value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
|
| +
|
| + // replace it
|
| + ReplaceWithValue(node, value, effect, control);
|
| + return Replace(value);
|
| +}
|
| +
|
| // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
|
| Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
|
| JSCallReduction r(node);
|
| @@ -1990,6 +2102,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
| case kNumberParseInt:
|
| reduction = ReduceNumberParseInt(node);
|
| break;
|
| + case kObjectCreate:
|
| + reduction = ReduceObjectCreate(node);
|
| + break;
|
| case kStringFromCharCode:
|
| reduction = ReduceStringFromCharCode(node);
|
| break;
|
|
|