Commit 5becebee authored by mvstanton's avatar mvstanton Committed by Commit bot

Wrap JSFunction bindings in a helper object.

We need to do other things with this bindings object, like store a feedback vector. Therefore, it's a good time to wrap it up in a helper class.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#31044}
parent 8499fa25
......@@ -4456,11 +4456,10 @@ Local<v8::Value> Function::GetBoundFunction() const {
if (!func->shared()->bound()) {
return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
}
i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
i::FixedArray::cast(func->function_bindings()));
i::Handle<i::Object> original(
bound_args->get(i::JSFunction::kBoundFunctionIndex),
func->GetIsolate());
i::Handle<i::BindingsArray> bound_args = i::Handle<i::BindingsArray>(
i::BindingsArray::cast(func->function_bindings()));
i::Handle<i::Object> original(bound_args->bound_function(),
func->GetIsolate());
return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
}
......
......@@ -746,9 +746,8 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function,
void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
Handle<FixedArray> new_bindings(function->function_bindings());
Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
isolate_);
Handle<BindingsArray> new_bindings(function->function_bindings());
Handle<Object> bindee(new_bindings->bound_function(), isolate_);
if (!bindee.is_null() && bindee->IsJSFunction()) {
Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
......
......@@ -731,6 +731,7 @@ bool Object::IsTypeFeedbackVector() const { return IsFixedArray(); }
bool Object::IsLiteralsArray() const { return IsFixedArray(); }
bool Object::IsBindingsArray() const { return IsFixedArray(); }
bool Object::IsDeoptimizationInputData() const {
......@@ -3506,6 +3507,75 @@ int LiteralsArray::literals_count() const {
}
Object* BindingsArray::get(int index) const { return FixedArray::get(index); }
void BindingsArray::set(int index, Object* value) {
FixedArray::set(index, value);
}
void BindingsArray::set(int index, Smi* value) {
FixedArray::set(index, value);
}
void BindingsArray::set(int index, Object* value, WriteBarrierMode mode) {
FixedArray::set(index, value, mode);
}
int BindingsArray::length() const { return FixedArray::length(); }
BindingsArray* BindingsArray::cast(Object* object) {
SLOW_DCHECK(object->IsBindingsArray());
return reinterpret_cast<BindingsArray*>(object);
}
void BindingsArray::set_feedback_vector(TypeFeedbackVector* vector) {
set(kVectorIndex, vector);
}
TypeFeedbackVector* BindingsArray::feedback_vector() const {
return TypeFeedbackVector::cast(get(kVectorIndex));
}
JSReceiver* BindingsArray::bound_function() const {
return JSReceiver::cast(get(kBoundFunctionIndex));
}
void BindingsArray::set_bound_function(JSReceiver* function) {
set(kBoundFunctionIndex, function);
}
Object* BindingsArray::bound_this() const { return get(kBoundThisIndex); }
void BindingsArray::set_bound_this(Object* bound_this) {
set(kBoundThisIndex, bound_this);
}
Object* BindingsArray::binding(int binding_index) const {
return get(kFirstBindingIndex + binding_index);
}
void BindingsArray::set_binding(int binding_index, Object* binding) {
set(kFirstBindingIndex + binding_index, binding);
}
int BindingsArray::bindings_count() const {
return length() - kFirstBindingIndex;
}
void HandlerTable::SetRangeStart(int index, int value) {
set(index * kRangeEntrySize + kRangeStartIndex, Smi::FromInt(value));
}
......@@ -6322,13 +6392,13 @@ void JSFunction::set_literals(LiteralsArray* literals) {
}
FixedArray* JSFunction::function_bindings() {
BindingsArray* JSFunction::function_bindings() {
DCHECK(shared()->bound());
return literals_or_bindings();
return BindingsArray::cast(literals_or_bindings());
}
void JSFunction::set_function_bindings(FixedArray* bindings) {
void JSFunction::set_function_bindings(BindingsArray* bindings) {
DCHECK(shared()->bound());
// Bound function literal may be initialized to the empty fixed array
// before the bindings are set.
......
......@@ -8815,6 +8815,47 @@ Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate,
}
// static
Handle<BindingsArray> BindingsArray::New(Isolate* isolate,
Handle<TypeFeedbackVector> vector,
Handle<JSReceiver> bound_function,
Handle<Object> bound_this,
int number_of_bindings) {
Handle<FixedArray> bindings = isolate->factory()->NewFixedArray(
number_of_bindings + kFirstBindingIndex);
Handle<BindingsArray> casted_bindings = Handle<BindingsArray>::cast(bindings);
casted_bindings->set_feedback_vector(*vector);
casted_bindings->set_bound_function(*bound_function);
casted_bindings->set_bound_this(*bound_this);
return casted_bindings;
}
// static
Handle<JSArray> BindingsArray::CreateBoundArguments(
Handle<BindingsArray> bindings) {
int bound_argument_count = bindings->bindings_count();
Factory* factory = bindings->GetIsolate()->factory();
Handle<FixedArray> arguments = factory->NewFixedArray(bound_argument_count);
bindings->CopyTo(kFirstBindingIndex, *arguments, 0, bound_argument_count);
return factory->NewJSArrayWithElements(arguments);
}
// static
Handle<JSArray> BindingsArray::CreateRuntimeBindings(
Handle<BindingsArray> bindings) {
Factory* factory = bindings->GetIsolate()->factory();
// A runtime bindings array consists of
// [bound function, bound this, [arg0, arg1, ...]].
Handle<FixedArray> runtime_bindings =
factory->NewFixedArray(2 + bindings->bindings_count());
bindings->CopyTo(kBoundFunctionIndex, *runtime_bindings, 0,
2 + bindings->bindings_count());
return factory->NewJSArrayWithElements(runtime_bindings);
}
int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out,
CatchPrediction* prediction_out) {
int innermost_handler = -1, innermost_start = -1;
......
......@@ -77,6 +77,7 @@
// - FixedArray
// - DescriptorArray
// - LiteralsArray
// - BindingsArray
// - HashTable
// - Dictionary
// - StringTable
......@@ -941,6 +942,7 @@ template <class C> inline bool Is(Object* obj);
V(LayoutDescriptor) \
V(Map) \
V(DescriptorArray) \
V(BindingsArray) \
V(TransitionArray) \
V(LiteralsArray) \
V(TypeFeedbackVector) \
......@@ -4606,6 +4608,48 @@ class LiteralsArray : public FixedArray {
};
// A bindings array contains the bindings for a bound function. It also holds
// the type feedback vector.
class BindingsArray : public FixedArray {
public:
inline TypeFeedbackVector* feedback_vector() const;
inline void set_feedback_vector(TypeFeedbackVector* vector);
inline JSReceiver* bound_function() const;
inline void set_bound_function(JSReceiver* function);
inline Object* bound_this() const;
inline void set_bound_this(Object* bound_this);
inline Object* binding(int binding_index) const;
inline void set_binding(int binding_index, Object* binding);
inline int bindings_count() const;
static Handle<BindingsArray> New(Isolate* isolate,
Handle<TypeFeedbackVector> vector,
Handle<JSReceiver> bound_function,
Handle<Object> bound_this,
int number_of_bindings);
static Handle<JSArray> CreateBoundArguments(Handle<BindingsArray> bindings);
static Handle<JSArray> CreateRuntimeBindings(Handle<BindingsArray> bindings);
DECLARE_CAST(BindingsArray)
private:
static const int kVectorIndex = 0;
static const int kBoundFunctionIndex = 1;
static const int kBoundThisIndex = 2;
static const int kFirstBindingIndex = 3;
inline Object* get(int index) const;
inline void set(int index, Object* value);
inline void set(int index, Smi* value);
inline void set(int index, Object* value, WriteBarrierMode mode);
inline int length() const;
};
// HandlerTable is a fixed array containing entries for exception handlers in
// the code object it is associated with. The tables comes in two flavors:
// 1) Based on ranges: Used for unoptimized code. Contains one entry per
......@@ -7176,8 +7220,8 @@ class JSFunction: public JSObject {
inline LiteralsArray* literals();
inline void set_literals(LiteralsArray* literals);
inline FixedArray* function_bindings();
inline void set_function_bindings(FixedArray* bindings);
inline BindingsArray* function_bindings();
inline void set_function_bindings(BindingsArray* bindings);
// The initial map for an object created by this constructor.
inline Map* initial_map();
......@@ -7264,11 +7308,6 @@ class JSFunction: public JSObject {
static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
static const int kSize = kNextFunctionLinkOffset + kPointerSize;
// Layout of the bound-function binding array.
static const int kBoundFunctionIndex = 0;
static const int kBoundThisIndex = 1;
static const int kBoundArgumentsStartIndex = 2;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
};
......
......@@ -1593,18 +1593,14 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
JSFunction* func = JSFunction::cast(js_obj);
if (func->shared()->bound()) {
FixedArray* bindings = func->function_bindings();
SetNativeBindReference(js_obj, entry, "bound_this",
bindings->get(JSFunction::kBoundThisIndex));
BindingsArray* bindings = func->function_bindings();
SetNativeBindReference(js_obj, entry, "bound_this", bindings->bound_this());
SetNativeBindReference(js_obj, entry, "bound_function",
bindings->get(JSFunction::kBoundFunctionIndex));
for (int i = JSFunction::kBoundArgumentsStartIndex;
i < bindings->length(); i++) {
const char* reference_name = names_->GetFormatted(
"bound_argument_%d",
i - JSFunction::kBoundArgumentsStartIndex);
bindings->bound_function());
for (int i = 0; i < bindings->bindings_count(); i++) {
const char* reference_name = names_->GetFormatted("bound_argument_%d", i);
SetNativeBindReference(js_obj, entry, reference_name,
bindings->get(i));
bindings->binding(i));
}
}
}
......
......@@ -156,29 +156,24 @@ MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
RUNTIME_ASSERT_HANDLIFIED(function->function_bindings()->IsFixedArray(),
JSArray);
Handle<FixedArray> bindings(function->function_bindings());
Handle<BindingsArray> bindings(function->function_bindings());
Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
Handle<String> target =
factory->NewStringFromAsciiChecked("[[TargetFunction]]");
result->set(0, *target);
result->set(1, bindings->get(JSFunction::kBoundFunctionIndex));
result->set(1, bindings->bound_function());
Handle<String> bound_this =
factory->NewStringFromAsciiChecked("[[BoundThis]]");
result->set(2, *bound_this);
result->set(3, bindings->get(JSFunction::kBoundThisIndex));
result->set(3, bindings->bound_this());
Handle<FixedArray> arguments = factory->NewFixedArray(
bindings->length() - JSFunction::kBoundArgumentsStartIndex);
bindings->CopyTo(
JSFunction::kBoundArgumentsStartIndex, *arguments, 0,
bindings->length() - JSFunction::kBoundArgumentsStartIndex);
Handle<String> bound_args =
factory->NewStringFromAsciiChecked("[[BoundArgs]]");
result->set(4, *bound_args);
Handle<JSArray> arguments_array =
factory->NewJSArrayWithElements(arguments);
BindingsArray::CreateBoundArguments(bindings);
result->set(5, *arguments_array);
return factory->NewJSArrayWithElements(result);
}
......
......@@ -357,7 +357,7 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, bindee, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
......@@ -378,30 +378,28 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
}
// Initialize array of bindings (function, this, and any existing arguments
// if the function was already bound).
Handle<FixedArray> new_bindings;
int i;
Handle<BindingsArray> new_bindings;
int out_index = 0;
Handle<TypeFeedbackVector> vector(
bound_function->shared()->feedback_vector());
if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
Handle<FixedArray> old_bindings(
Handle<BindingsArray> old_bindings(
JSFunction::cast(*bindee)->function_bindings());
RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex);
new_bindings =
isolate->factory()->NewFixedArray(old_bindings->length() + argc);
bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
isolate);
i = 0;
for (int n = old_bindings->length(); i < n; i++) {
new_bindings->set(i, old_bindings->get(i));
RUNTIME_ASSERT(old_bindings->bindings_count() >= 0);
bindee = handle(old_bindings->bound_function(), isolate);
Handle<Object> old_bound_this(old_bindings->bound_this(), isolate);
new_bindings = BindingsArray::New(isolate, vector, bindee, old_bound_this,
old_bindings->bindings_count() + argc);
for (int n = old_bindings->bindings_count(); out_index < n; out_index++) {
new_bindings->set_binding(out_index, old_bindings->binding(out_index));
}
} else {
int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
new_bindings = isolate->factory()->NewFixedArray(array_size);
new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
new_bindings->set(JSFunction::kBoundThisIndex, *this_object);
i = 2;
new_bindings =
BindingsArray::New(isolate, vector, bindee, this_object, argc);
}
// Copy arguments, skipping the first which is "this_arg".
for (int j = 0; j < argc; j++, i++) {
new_bindings->set(i, *arguments[j + 1]);
for (int j = 0; j < argc; j++, out_index++) {
new_bindings->set_binding(out_index, *arguments[j + 1]);
}
new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
bound_function->set_function_bindings(*new_bindings);
......@@ -445,9 +443,9 @@ RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
if (callable->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
if (function->shared()->bound()) {
RUNTIME_ASSERT(function->function_bindings()->IsFixedArray());
Handle<FixedArray> bindings(function->function_bindings());
return *isolate->factory()->NewJSArrayWithElements(bindings);
RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray());
Handle<BindingsArray> bindings(function->function_bindings());
return *BindingsArray::CreateRuntimeBindings(bindings);
}
}
return isolate->heap()->undefined_value();
......@@ -463,12 +461,10 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
// The argument is a bound function. Extract its bound arguments
// and callable.
Handle<FixedArray> bound_args =
Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
Handle<Object> bound_function(
JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
isolate);
Handle<BindingsArray> bound_args =
handle(BindingsArray::cast(function->function_bindings()));
int bound_argc = bound_args->bindings_count();
Handle<Object> bound_function(bound_args->bound_function(), isolate);
DCHECK(!bound_function->IsJSFunction() ||
!Handle<JSFunction>::cast(bound_function)->shared()->bound());
......@@ -476,8 +472,7 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
base::SmartArrayPointer<Handle<Object>> param_data =
Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
for (int i = 0; i < bound_argc; i++) {
param_data[i] = Handle<Object>(
bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate);
param_data[i] = handle(bound_args->binding(i), isolate);
}
Handle<Object> result;
......
......@@ -1562,9 +1562,8 @@ RUNTIME_FUNCTION(Runtime_InstanceOf) {
if (callable->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
if (function->shared()->bound()) {
Handle<FixedArray> bindings(function->function_bindings(), isolate);
callable =
handle(bindings->get(JSFunction::kBoundFunctionIndex), isolate);
Handle<BindingsArray> bindings(function->function_bindings(), isolate);
callable = handle(bindings->bound_function(), isolate);
}
}
DCHECK(callable->IsCallable());
......
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