Commit d4a47fe6 authored by ishell's avatar ishell Committed by Commit bot

[ic] Smi-handlers are now able to represent loads of constants from descriptor array.

BUG=

Review-Url: https://codereview.chromium.org/2418063003
Cr-Commit-Position: refs/heads/master@{#40324}
parent 74a392cc
......@@ -4855,7 +4855,7 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_cell_handler);
// |handler| is a Smi, encoding what to do. See handler-configuration.h
// |handler| is a Smi, encoding what to do. See SmiHandler methods
// for the encoding format.
Bind(&if_smi_handler);
{
......@@ -4864,10 +4864,10 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
Node* holder = var_holder.value();
Node* handler_word = SmiUntag(var_smi_handler.value());
Node* handler_type =
WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBits::kMask));
if (support_elements == kSupportElements) {
Label property(this);
Node* handler_type =
WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask));
GotoUnless(
WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)),
&property);
......@@ -4914,44 +4914,65 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
Comment("property_load");
}
// |handler_word| is a field index as obtained by
// FieldIndex.GetLoadByFieldOffset():
Label inobject_double(this), out_of_object(this),
out_of_object_double(this);
Node* inobject_bit =
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask));
Node* double_bit =
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask));
Node* offset =
WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift));
GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object);
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double);
Return(LoadObjectField(holder, offset));
Bind(&inobject_double);
if (FLAG_unbox_double_fields) {
var_double_value.Bind(
LoadObjectField(holder, offset, MachineType::Float64()));
} else {
Node* mutable_heap_number = LoadObjectField(holder, offset);
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
}
Goto(&rebox_double);
Label constant(this), field(this);
Branch(WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForFields)),
&field, &constant);
Bind(&out_of_object);
Node* properties = LoadProperties(holder);
Node* value = LoadObjectField(properties, offset);
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double);
Return(value);
Bind(&field);
{
Comment("field_load");
Label inobject_double(this), out_of_object(this),
out_of_object_double(this);
Node* inobject_bit =
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask));
Node* double_bit =
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask));
Node* offset =
WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift));
GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object);
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double);
Return(LoadObjectField(holder, offset));
Bind(&inobject_double);
if (FLAG_unbox_double_fields) {
var_double_value.Bind(
LoadObjectField(holder, offset, MachineType::Float64()));
} else {
Node* mutable_heap_number = LoadObjectField(holder, offset);
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
}
Goto(&rebox_double);
Bind(&out_of_object_double);
var_double_value.Bind(LoadHeapNumberValue(value));
Goto(&rebox_double);
Bind(&out_of_object);
Node* properties = LoadProperties(holder);
Node* value = LoadObjectField(properties, offset);
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)),
&out_of_object_double);
Return(value);
Bind(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value()));
Bind(&out_of_object_double);
var_double_value.Bind(LoadHeapNumberValue(value));
Goto(&rebox_double);
Bind(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value()));
}
Bind(&constant);
{
Comment("constant_load");
Node* descriptors = LoadMapDescriptors(LoadMap(holder));
Node* descriptor = WordSar(
handler_word, IntPtrConstant(ValueIndexInDescriptorArray::kShift));
#if defined(DEBUG)
Assert(UintPtrLessThan(descriptor,
LoadAndUntagFixedArrayBaseLength(descriptors)));
#endif
Return(
LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS));
}
}
Bind(&try_proto_cell_handler);
......
......@@ -729,6 +729,7 @@ class RuntimeCallTimer {
V(LoadIC_FunctionPrototypeStub) \
V(LoadIC_LoadApiGetterStub) \
V(LoadIC_LoadCallback) \
V(LoadIC_LoadConstantDH) \
V(LoadIC_LoadConstant) \
V(LoadIC_LoadConstantStub) \
V(LoadIC_LoadFieldDH) \
......
......@@ -8,24 +8,33 @@
#include "src/ic/handler-configuration.h"
#include "src/field-index-inl.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
Handle<Object> SmiHandler::MakeLoadFieldHandler(Isolate* isolate,
FieldIndex field_index) {
int config = LoadHandlerTypeBit::encode(kLoadICHandlerForProperties) |
int config = LoadHandlerTypeBits::encode(kLoadICHandlerForFields) |
FieldOffsetIsInobject::encode(field_index.is_inobject()) |
FieldOffsetIsDouble::encode(field_index.is_double()) |
FieldOffsetOffset::encode(field_index.offset());
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> SmiHandler::MakeLoadConstantHandler(Isolate* isolate,
int descriptor) {
int config = LoadHandlerTypeBits::encode(kLoadICHandlerForConstants) |
ValueIndexInDescriptorArray::encode(
DescriptorArray::ToValueIndex(descriptor));
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> SmiHandler::MakeKeyedLoadHandler(Isolate* isolate,
ElementsKind elements_kind,
bool convert_hole_to_undefined,
bool is_js_array) {
int config = LoadHandlerTypeBit::encode(kLoadICHandlerForElements) |
int config = LoadHandlerTypeBits::encode(kLoadICHandlerForElements) |
KeyedLoadElementsKind::encode(elements_kind) |
KeyedLoadConvertHole::encode(convert_hole_to_undefined) |
KeyedLoadIsJsArray::encode(is_js_array);
......
......@@ -15,24 +15,35 @@ namespace internal {
enum LoadHandlerType {
kLoadICHandlerForElements = 0,
kLoadICHandlerForProperties = 1
kLoadICHandlerForFields = 1,
kLoadICHandlerForConstants = 2
};
class LoadHandlerTypeBit : public BitField<LoadHandlerType, 0, 1> {};
class LoadHandlerTypeBits : public BitField<LoadHandlerType, 0, 2> {};
// Encoding for configuration Smis for property loads:
// Encoding for configuration Smis for constants loads (when LoadHandlerTypeBits
// contain LoadICHandlerForConstants):
class ValueIndexInDescriptorArray
: public BitField<int, LoadHandlerTypeBits::kNext,
kDescriptorIndexBitCount + 2> {};
// Make sure we don't overflow into the sign bit.
STATIC_ASSERT(ValueIndexInDescriptorArray::kNext <= kSmiValueSize - 1);
// Encoding for configuration Smis for field loads (when LoadHandlerTypeBits
// contain LoadICHandlerForFields):
class FieldOffsetIsInobject
: public BitField<bool, LoadHandlerTypeBit::kNext, 1> {};
: public BitField<bool, LoadHandlerTypeBits::kNext, 1> {};
class FieldOffsetIsDouble
: public BitField<bool, FieldOffsetIsInobject::kNext, 1> {};
class FieldOffsetOffset : public BitField<int, FieldOffsetIsDouble::kNext, 27> {
class FieldOffsetOffset : public BitField<int, FieldOffsetIsDouble::kNext, 26> {
};
// Make sure we don't overflow into the sign bit.
STATIC_ASSERT(FieldOffsetOffset::kNext <= kSmiValueSize - 1);
// Encoding for configuration Smis for elements loads:
class KeyedLoadIsJsArray : public BitField<bool, LoadHandlerTypeBit::kNext, 1> {
};
// Encoding for configuration Smis for elements loads (when LoadHandlerTypeBits
// contain LoadICHandlerForElements)
class KeyedLoadIsJsArray
: public BitField<bool, LoadHandlerTypeBits::kNext, 1> {};
class KeyedLoadConvertHole
: public BitField<bool, KeyedLoadIsJsArray::kNext, 1> {};
class KeyedLoadElementsKind
......@@ -47,6 +58,9 @@ class SmiHandler {
static inline Handle<Object> MakeLoadFieldHandler(Isolate* isolate,
FieldIndex field_index);
static inline Handle<Object> MakeLoadConstantHandler(Isolate* isolate,
int descriptor);
static inline Handle<Object> MakeKeyedLoadHandler(
Isolate* isolate, ElementsKind elements_kind,
bool convert_hole_to_undefined, bool is_js_array);
......
......@@ -1210,6 +1210,11 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
// -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == DATA_CONSTANT);
if (receiver_is_holder) {
if (FLAG_tf_load_ic_stub) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
return SmiHandler::MakeLoadConstantHandler(
isolate(), lookup->GetConstantIndex());
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
return stub.GetCode();
......
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