2012-01-24 08:43:12 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-06-20 08:40:11 +00:00
|
|
|
#include "src/accessors.h"
|
2015-08-14 09:41:32 +00:00
|
|
|
|
2014-06-20 08:40:11 +00:00
|
|
|
#include "src/api.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/contexts.h"
|
|
|
|
#include "src/deoptimizer.h"
|
|
|
|
#include "src/execution.h"
|
|
|
|
#include "src/factory.h"
|
|
|
|
#include "src/frames-inl.h"
|
2015-09-01 09:25:19 +00:00
|
|
|
#include "src/isolate-inl.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/list-inl.h"
|
2015-05-06 07:51:56 +00:00
|
|
|
#include "src/messages.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/property-details.h"
|
2014-07-14 07:19:49 +00:00
|
|
|
#include "src/prototype.h"
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2009-05-25 10:05:56 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
2014-04-29 10:59:14 +00:00
|
|
|
Handle<AccessorInfo> Accessors::MakeAccessor(
|
|
|
|
Isolate* isolate,
|
2014-08-20 15:25:13 +00:00
|
|
|
Handle<Name> name,
|
|
|
|
AccessorNameGetterCallback getter,
|
|
|
|
AccessorNameSetterCallback setter,
|
2014-04-29 10:59:14 +00:00
|
|
|
PropertyAttributes attributes) {
|
2014-04-15 13:25:17 +00:00
|
|
|
Factory* factory = isolate->factory();
|
2016-01-18 15:08:36 +00:00
|
|
|
Handle<AccessorInfo> info = factory->NewAccessorInfo();
|
2014-04-15 13:25:17 +00:00
|
|
|
info->set_property_attributes(attributes);
|
2014-04-28 13:41:12 +00:00
|
|
|
info->set_all_can_read(false);
|
|
|
|
info->set_all_can_write(false);
|
2015-05-18 12:36:49 +00:00
|
|
|
info->set_is_special_data_property(true);
|
2014-04-16 11:57:23 +00:00
|
|
|
info->set_name(*name);
|
2014-04-15 13:25:17 +00:00
|
|
|
Handle<Object> get = v8::FromCData(isolate, getter);
|
|
|
|
Handle<Object> set = v8::FromCData(isolate, setter);
|
|
|
|
info->set_getter(*get);
|
|
|
|
info->set_setter(*set);
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-11 12:57:25 +00:00
|
|
|
static V8_INLINE bool CheckForName(Handle<Name> name,
|
2014-04-11 07:27:25 +00:00
|
|
|
Handle<String> property_name,
|
2013-09-25 08:19:35 +00:00
|
|
|
int offset,
|
|
|
|
int* object_offset) {
|
2014-08-11 12:57:25 +00:00
|
|
|
if (Name::Equals(name, property_name)) {
|
2013-09-25 08:19:35 +00:00
|
|
|
*object_offset = offset;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-04 12:44:15 +00:00
|
|
|
// Returns true for properties that are accessors to object fields.
|
|
|
|
// If true, *object_offset contains offset of object field.
|
2015-02-17 15:33:26 +00:00
|
|
|
bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
|
2014-01-30 11:30:38 +00:00
|
|
|
int* object_offset) {
|
|
|
|
Isolate* isolate = name->GetIsolate();
|
|
|
|
|
2013-09-25 08:19:35 +00:00
|
|
|
switch (map->instance_type()) {
|
|
|
|
case JS_ARRAY_TYPE:
|
|
|
|
return
|
2014-04-11 07:27:25 +00:00
|
|
|
CheckForName(name, isolate->factory()->length_string(),
|
2013-09-25 08:19:35 +00:00
|
|
|
JSArray::kLengthOffset, object_offset);
|
2015-04-27 09:28:16 +00:00
|
|
|
case JS_ARRAY_BUFFER_TYPE:
|
|
|
|
return CheckForName(name, isolate->factory()->byte_length_string(),
|
|
|
|
JSArrayBuffer::kByteLengthOffset, object_offset);
|
|
|
|
default:
|
|
|
|
if (map->instance_type() < FIRST_NONSTRING_TYPE) {
|
|
|
|
return CheckForName(name, isolate->factory()->length_string(),
|
|
|
|
String::kLengthOffset, object_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
|
|
|
|
Handle<Name> name,
|
|
|
|
int* object_offset) {
|
|
|
|
Isolate* isolate = name->GetIsolate();
|
|
|
|
|
|
|
|
switch (map->instance_type()) {
|
2015-09-10 12:21:47 +00:00
|
|
|
case JS_TYPED_ARRAY_TYPE: {
|
|
|
|
if (!CheckForName(name, isolate->factory()->length_string(),
|
|
|
|
JSTypedArray::kLengthOffset, object_offset) &&
|
|
|
|
!CheckForName(name, isolate->factory()->byte_length_string(),
|
|
|
|
JSTypedArray::kByteLengthOffset, object_offset) &&
|
|
|
|
!CheckForName(name, isolate->factory()->byte_offset_string(),
|
|
|
|
JSTypedArray::kByteOffsetOffset, object_offset)) {
|
2015-04-22 15:03:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-04-27 09:28:16 +00:00
|
|
|
|
2015-09-10 12:21:47 +00:00
|
|
|
if (map->is_dictionary_map()) return false;
|
|
|
|
|
|
|
|
// Check if the property is overridden on the instance.
|
|
|
|
DescriptorArray* descriptors = map->instance_descriptors();
|
|
|
|
int descriptor = descriptors->SearchWithCache(*name, *map);
|
|
|
|
if (descriptor != DescriptorArray::kNotFound) return false;
|
|
|
|
|
|
|
|
Handle<Object> proto = Handle<Object>(map->prototype(), isolate);
|
|
|
|
if (!proto->IsJSReceiver()) return false;
|
|
|
|
|
|
|
|
// Check if the property is defined in the prototype chain.
|
|
|
|
LookupIterator it(proto, name);
|
|
|
|
if (!it.IsFound()) return false;
|
|
|
|
|
|
|
|
Object* original_proto =
|
|
|
|
JSFunction::cast(map->GetConstructor())->prototype();
|
|
|
|
|
|
|
|
// Property is not configurable. It is enough to verify that
|
|
|
|
// the holder is the same.
|
|
|
|
return *it.GetHolder<Object>() == original_proto;
|
|
|
|
}
|
2015-04-22 15:03:25 +00:00
|
|
|
case JS_DATA_VIEW_TYPE:
|
2015-04-27 09:28:16 +00:00
|
|
|
return CheckForName(name, isolate->factory()->byte_length_string(),
|
|
|
|
JSDataView::kByteLengthOffset, object_offset) ||
|
|
|
|
CheckForName(name, isolate->factory()->byte_offset_string(),
|
|
|
|
JSDataView::kByteOffsetOffset, object_offset);
|
2014-01-30 11:30:38 +00:00
|
|
|
default:
|
2013-09-25 08:19:35 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-25 09:12:22 +00:00
|
|
|
//
|
|
|
|
// Accessors::ArgumentsIterator
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ArgumentsIteratorGetter(
|
|
|
|
v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* result = isolate->native_context()->array_values_iterator();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ArgumentsIteratorSetter(
|
|
|
|
v8::Local<v8::Name> name, v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
2015-11-16 16:48:43 +00:00
|
|
|
Handle<JSObject> object_handle =
|
|
|
|
Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
|
2015-09-14 07:19:58 +00:00
|
|
|
Handle<Object> value_handle = Utils::OpenHandle(*val);
|
|
|
|
Handle<Name> name_handle = Utils::OpenHandle(*name);
|
2014-08-25 09:12:22 +00:00
|
|
|
|
2015-09-14 07:19:58 +00:00
|
|
|
if (JSObject::DefinePropertyOrElementIgnoreAttributes(
|
|
|
|
object_handle, name_handle, value_handle, NONE)
|
|
|
|
.is_null()) {
|
2014-10-14 14:46:11 +00:00
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
}
|
2014-08-25 09:12:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
2014-11-13 08:47:52 +00:00
|
|
|
Handle<Name> name = isolate->factory()->iterator_symbol();
|
2014-08-25 09:12:22 +00:00
|
|
|
return MakeAccessor(isolate, name, &ArgumentsIteratorGetter,
|
|
|
|
&ArgumentsIteratorSetter, attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
// Accessors::ArrayLength
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-28 14:59:29 +00:00
|
|
|
void Accessors::ArrayLengthGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 14:59:29 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
2013-11-05 13:47:51 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
|
|
|
|
Object* result = holder->length();
|
2014-04-28 14:59:29 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
|
|
|
|
}
|
2013-11-05 13:47:51 +00:00
|
|
|
|
2014-04-28 14:59:29 +00:00
|
|
|
|
|
|
|
void Accessors::ArrayLengthSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 14:59:29 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2015-11-16 16:48:43 +00:00
|
|
|
Handle<JSReceiver> object = Utils::OpenHandle(*info.This());
|
2015-06-19 15:27:40 +00:00
|
|
|
Handle<JSArray> array = Handle<JSArray>::cast(object);
|
|
|
|
Handle<Object> length_obj = Utils::OpenHandle(*val);
|
|
|
|
|
|
|
|
uint32_t length = 0;
|
2015-10-15 16:03:20 +00:00
|
|
|
if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
return;
|
2014-04-28 14:59:29 +00:00
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2015-06-19 15:27:40 +00:00
|
|
|
if (JSArray::ObservableSetLength(array, length).is_null()) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
2016-01-22 09:53:29 +00:00
|
|
|
|
|
|
|
if (info.ShouldThrowOnError()) {
|
|
|
|
uint32_t actual_new_len = 0;
|
|
|
|
CHECK(array->length()->ToArrayLength(&actual_new_len));
|
|
|
|
// Throw TypeError if there were non-deletable elements.
|
|
|
|
if (actual_new_len != length) {
|
|
|
|
Factory* factory = isolate->factory();
|
|
|
|
isolate->Throw(*factory->NewTypeError(
|
|
|
|
MessageTemplate::kStrictDeleteProperty,
|
|
|
|
factory->NewNumberFromUint(actual_new_len - 1), array));
|
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
}
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 14:59:29 +00:00
|
|
|
Handle<AccessorInfo> Accessors::ArrayLengthInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->length_string(),
|
|
|
|
&ArrayLengthGetter,
|
|
|
|
&ArrayLengthSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::StringLength
|
|
|
|
//
|
|
|
|
|
2014-04-15 13:25:17 +00:00
|
|
|
void Accessors::StringLengthGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-15 13:25:17 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
|
|
|
|
// We have a slight impedance mismatch between the external API and the way we
|
|
|
|
// use callbacks internally: Externally, callbacks can only be used with
|
|
|
|
// v8::Object, but internally we have callbacks on entities which are higher
|
|
|
|
// in the hierarchy, in this case for String values.
|
|
|
|
|
|
|
|
Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
|
|
|
|
if (!value->IsString()) {
|
|
|
|
// Not a string value. That means that we either got a String wrapper or
|
|
|
|
// a Value with a String wrapper in its prototype chain.
|
|
|
|
value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
|
2014-04-15 13:25:17 +00:00
|
|
|
}
|
2014-07-23 20:11:33 +00:00
|
|
|
Object* result = Smi::FromInt(String::cast(value)->length());
|
2014-04-15 13:25:17 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
|
|
|
|
}
|
2014-04-10 12:00:36 +00:00
|
|
|
|
2014-04-15 13:25:17 +00:00
|
|
|
|
|
|
|
void Accessors::StringLengthSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-15 13:25:17 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-15 13:25:17 +00:00
|
|
|
Handle<AccessorInfo> Accessors::StringLengthInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->length_string(),
|
|
|
|
&StringLengthGetter,
|
|
|
|
&StringLengthSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2014-04-16 11:57:23 +00:00
|
|
|
// Accessors::ScriptColumnOffset
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptColumnOffsetGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
2015-09-28 13:10:13 +00:00
|
|
|
Object* res = Smi::FromInt(
|
|
|
|
Script::cast(JSValue::cast(object)->value())->column_offset());
|
2014-04-16 11:57:23 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptColumnOffsetSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("column_offset")));
|
2014-04-16 11:57:23 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptColumnOffsetGetter,
|
|
|
|
&ScriptColumnOffsetSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2014-04-16 11:57:23 +00:00
|
|
|
// Accessors::ScriptId
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptIdGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
2015-09-28 13:10:13 +00:00
|
|
|
Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id());
|
2014-04-16 11:57:23 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptIdSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptIdInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
2014-09-10 12:38:12 +00:00
|
|
|
Handle<String> name(
|
|
|
|
isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
|
2014-04-16 11:57:23 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptIdGetter,
|
|
|
|
&ScriptIdSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
2009-03-10 08:10:50 +00:00
|
|
|
//
|
2014-04-16 11:57:23 +00:00
|
|
|
// Accessors::ScriptName
|
2009-03-10 08:10:50 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptNameGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* source = Script::cast(JSValue::cast(object)->value())->name();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
|
2009-03-10 08:10:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptNameSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptNameInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->name_string(),
|
|
|
|
&ScriptNameGetter,
|
|
|
|
&ScriptNameSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-03-10 08:10:50 +00:00
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
2014-04-16 11:57:23 +00:00
|
|
|
// Accessors::ScriptSource
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptSourceGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* source = Script::cast(JSValue::cast(object)->value())->source();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptSourceSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptSourceInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->source_string(),
|
|
|
|
&ScriptSourceGetter,
|
|
|
|
&ScriptSourceSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2014-04-16 11:57:23 +00:00
|
|
|
// Accessors::ScriptLineOffset
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
void Accessors::ScriptLineOffsetGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
2015-09-28 13:10:13 +00:00
|
|
|
Object* res =
|
|
|
|
Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset());
|
2014-04-16 11:57:23 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptLineOffsetSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 11:57:23 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 11:57:23 +00:00
|
|
|
Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("line_offset")));
|
2014-04-16 11:57:23 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptLineOffsetGetter,
|
|
|
|
&ScriptLineOffsetSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::ScriptType
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptTypeGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
2015-09-28 13:10:13 +00:00
|
|
|
Object* res =
|
|
|
|
Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type());
|
2014-04-16 14:30:58 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptTypeSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptTypeInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
2014-09-10 12:38:12 +00:00
|
|
|
Handle<String> name(
|
|
|
|
isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptTypeGetter,
|
|
|
|
&ScriptTypeSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
2009-06-08 10:47:49 +00:00
|
|
|
//
|
|
|
|
// Accessors::ScriptCompilationType
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptCompilationTypeGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* res = Smi::FromInt(
|
|
|
|
Script::cast(JSValue::cast(object)->value())->compilation_type());
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
2009-06-08 10:47:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptCompilationTypeSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("compilation_type")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptCompilationTypeGetter,
|
|
|
|
&ScriptCompilationTypeSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-06-08 10:47:49 +00:00
|
|
|
|
|
|
|
|
2009-02-04 12:07:45 +00:00
|
|
|
//
|
|
|
|
// Accessors::ScriptGetLineEnds
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptLineEndsGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
2011-03-29 07:34:23 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-04-16 14:30:58 +00:00
|
|
|
Handle<Object> object = Utils::OpenHandle(*info.This());
|
|
|
|
Handle<Script> script(
|
|
|
|
Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
|
2014-04-16 13:28:11 +00:00
|
|
|
Script::InitLineEnds(script);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(script->line_ends()->IsFixedArray());
|
2009-11-27 14:10:48 +00:00
|
|
|
Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
|
2010-11-17 12:49:27 +00:00
|
|
|
// We do not want anyone to modify this array from JS.
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
|
2011-03-29 07:34:23 +00:00
|
|
|
line_ends->map() == isolate->heap()->fixed_cow_array_map());
|
|
|
|
Handle<JSArray> js_array =
|
|
|
|
isolate->factory()->NewJSArrayWithElements(line_ends);
|
2014-04-16 14:30:58 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(js_array));
|
2009-02-04 12:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptLineEndsSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("line_ends")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptLineEndsGetter,
|
|
|
|
&ScriptLineEndsSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-02-04 12:07:45 +00:00
|
|
|
|
|
|
|
|
2014-07-02 07:01:31 +00:00
|
|
|
//
|
|
|
|
// Accessors::ScriptSourceUrl
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptSourceUrlGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-07-02 07:01:31 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptSourceUrlSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-07-02 07:01:31 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->source_url_string(),
|
|
|
|
&ScriptSourceUrlGetter,
|
|
|
|
&ScriptSourceUrlSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::ScriptSourceMappingUrl
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptSourceMappingUrlGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-07-02 07:01:31 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* url =
|
|
|
|
Script::cast(JSValue::cast(object)->value())->source_mapping_url();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptSourceMappingUrlSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-07-02 07:01:31 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->source_mapping_url_string(),
|
|
|
|
&ScriptSourceMappingUrlGetter,
|
|
|
|
&ScriptSourceMappingUrlSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-29 14:01:13 +00:00
|
|
|
//
|
|
|
|
// Accessors::ScriptIsEmbedderDebugScript
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptIsEmbedderDebugScriptGetter(
|
|
|
|
v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
2015-05-19 03:11:33 +00:00
|
|
|
bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
|
|
|
|
->origin_options()
|
|
|
|
.IsEmbedderDebugScript();
|
2015-01-29 14:01:13 +00:00
|
|
|
Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script);
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::ScriptIsEmbedderDebugScriptSetter(
|
|
|
|
v8::Local<v8::Name> name, v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
|
|
|
STATIC_CHAR_VECTOR("is_debugger_script")));
|
|
|
|
return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter,
|
|
|
|
&ScriptIsEmbedderDebugScriptSetter, attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-06 08:52:48 +00:00
|
|
|
//
|
|
|
|
// Accessors::ScriptGetContextData
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptContextDataGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Object* object = *Utils::OpenHandle(*info.This());
|
|
|
|
Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
|
2009-05-06 08:52:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptContextDataSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("context_data")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptContextDataGetter,
|
|
|
|
&ScriptContextDataSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-05-06 08:52:48 +00:00
|
|
|
|
|
|
|
|
2009-06-08 10:47:49 +00:00
|
|
|
//
|
2009-12-01 14:36:45 +00:00
|
|
|
// Accessors::ScriptGetEvalFromScript
|
2009-06-08 10:47:49 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromScriptGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Handle<Object> object = Utils::OpenHandle(*info.This());
|
|
|
|
Handle<Script> script(
|
|
|
|
Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
|
|
|
|
Handle<Object> result = isolate->factory()->undefined_value();
|
|
|
|
if (!script->eval_from_shared()->IsUndefined()) {
|
2009-12-01 14:36:45 +00:00
|
|
|
Handle<SharedFunctionInfo> eval_from_shared(
|
2014-04-16 14:30:58 +00:00
|
|
|
SharedFunctionInfo::cast(script->eval_from_shared()));
|
2009-12-01 14:36:45 +00:00
|
|
|
if (eval_from_shared->script()->IsScript()) {
|
|
|
|
Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
|
2014-04-16 14:30:58 +00:00
|
|
|
result = Script::GetWrapper(eval_from_script);
|
2009-12-01 14:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-16 14:30:58 +00:00
|
|
|
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2009-06-08 10:47:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromScriptSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("eval_from_script")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptEvalFromScriptGetter,
|
|
|
|
&ScriptEvalFromScriptSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-06-08 10:47:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2009-12-01 14:36:45 +00:00
|
|
|
// Accessors::ScriptGetEvalFromScriptPosition
|
2009-06-08 10:47:49 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromScriptPositionGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
2013-09-02 09:25:20 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-04-16 14:30:58 +00:00
|
|
|
Handle<Object> object = Utils::OpenHandle(*info.This());
|
|
|
|
Handle<Script> script(
|
|
|
|
Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
|
|
|
|
Handle<Object> result = isolate->factory()->undefined_value();
|
|
|
|
if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
|
|
|
|
Handle<Code> code(SharedFunctionInfo::cast(
|
|
|
|
script->eval_from_shared())->code());
|
2015-09-28 13:10:13 +00:00
|
|
|
result = Handle<Object>(Smi::FromInt(code->SourcePosition(
|
|
|
|
code->instruction_start() +
|
|
|
|
script->eval_from_instructions_offset())),
|
|
|
|
isolate);
|
2009-06-08 10:47:49 +00:00
|
|
|
}
|
2014-04-16 14:30:58 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
|
|
|
}
|
|
|
|
|
2009-06-08 10:47:49 +00:00
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromScriptPositionSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
2009-06-08 10:47:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("eval_from_script_position")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptEvalFromScriptPositionGetter,
|
|
|
|
&ScriptEvalFromScriptPositionSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-12-01 14:36:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::ScriptGetEvalFromFunctionName
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromFunctionNameGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Handle<Object> object = Utils::OpenHandle(*info.This());
|
|
|
|
Handle<Script> script(
|
|
|
|
Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
|
|
|
|
Handle<Object> result;
|
|
|
|
Handle<SharedFunctionInfo> shared(
|
|
|
|
SharedFunctionInfo::cast(script->eval_from_shared()));
|
2009-12-01 14:36:45 +00:00
|
|
|
// Find the name of the function calling eval.
|
|
|
|
if (!shared->name()->IsUndefined()) {
|
2014-04-16 14:30:58 +00:00
|
|
|
result = Handle<Object>(shared->name(), isolate);
|
2009-12-01 14:36:45 +00:00
|
|
|
} else {
|
2014-04-16 14:30:58 +00:00
|
|
|
result = Handle<Object>(shared->inferred_name(), isolate);
|
2009-12-01 14:36:45 +00:00
|
|
|
}
|
2014-04-16 14:30:58 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2009-12-01 14:36:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:30:58 +00:00
|
|
|
void Accessors::ScriptEvalFromFunctionNameSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-16 14:30:58 +00:00
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
Handle<String> name(isolate->factory()->InternalizeOneByteString(
|
2014-09-10 12:38:12 +00:00
|
|
|
STATIC_CHAR_VECTOR("eval_from_function_name")));
|
2014-04-16 14:30:58 +00:00
|
|
|
return MakeAccessor(isolate,
|
|
|
|
name,
|
|
|
|
&ScriptEvalFromFunctionNameGetter,
|
|
|
|
&ScriptEvalFromFunctionNameSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2009-06-08 10:47:49 +00:00
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
|
|
|
// Accessors::FunctionPrototype
|
|
|
|
//
|
|
|
|
|
2014-04-17 09:12:19 +00:00
|
|
|
static Handle<Object> GetFunctionPrototype(Isolate* isolate,
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function) {
|
2014-04-17 09:12:19 +00:00
|
|
|
if (!function->has_prototype()) {
|
|
|
|
Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
|
|
|
|
JSFunction::SetPrototype(function, proto);
|
|
|
|
}
|
|
|
|
return Handle<Object>(function->prototype(), isolate);
|
2013-08-16 21:27:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-14 14:46:11 +00:00
|
|
|
MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
|
|
|
|
Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
|
2012-12-10 10:53:57 +00:00
|
|
|
Handle<Object> old_value;
|
2014-07-24 16:42:54 +00:00
|
|
|
bool is_observed = function->map()->is_observed();
|
2012-12-10 10:53:57 +00:00
|
|
|
if (is_observed) {
|
|
|
|
if (function->has_prototype())
|
|
|
|
old_value = handle(function->prototype(), isolate);
|
|
|
|
else
|
|
|
|
old_value = isolate->factory()->NewFunctionPrototype(function);
|
|
|
|
}
|
|
|
|
|
2013-07-18 07:59:48 +00:00
|
|
|
JSFunction::SetPrototype(function, value);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(function->prototype() == *value);
|
2012-12-10 10:53:57 +00:00
|
|
|
|
|
|
|
if (is_observed && !old_value->SameValue(*value)) {
|
2014-10-14 14:46:11 +00:00
|
|
|
MaybeHandle<Object> result = JSObject::EnqueueChangeRecord(
|
2013-11-06 12:14:24 +00:00
|
|
|
function, "update", isolate->factory()->prototype_string(), old_value);
|
2014-10-14 14:46:11 +00:00
|
|
|
if (result.is_null()) return MaybeHandle<Object>();
|
2010-10-25 15:22:03 +00:00
|
|
|
}
|
2012-12-10 10:53:57 +00:00
|
|
|
|
2014-04-17 09:12:19 +00:00
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-14 14:46:11 +00:00
|
|
|
MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
|
|
|
|
Handle<Object> prototype) {
|
2015-09-24 06:50:01 +00:00
|
|
|
DCHECK(function->IsConstructor());
|
2014-04-17 09:12:19 +00:00
|
|
|
Isolate* isolate = function->GetIsolate();
|
2014-04-24 08:35:53 +00:00
|
|
|
return SetFunctionPrototype(isolate, function, prototype);
|
2014-04-17 09:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 08:35:53 +00:00
|
|
|
void Accessors::FunctionPrototypeGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-24 08:35:53 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
2014-04-17 09:12:19 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
|
|
|
Handle<Object> result = GetFunctionPrototype(isolate, function);
|
2014-04-24 08:35:53 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2014-04-17 09:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 08:35:53 +00:00
|
|
|
void Accessors::FunctionPrototypeSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-24 08:35:53 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Handle<Object> value = Utils::OpenHandle(*val);
|
2014-07-24 16:42:54 +00:00
|
|
|
Handle<JSFunction> object =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
2014-10-14 14:46:11 +00:00
|
|
|
if (SetFunctionPrototype(isolate, object, value).is_null()) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 08:35:53 +00:00
|
|
|
Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->prototype_string(),
|
|
|
|
&FunctionPrototypeGetter,
|
|
|
|
&FunctionPrototypeSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::FunctionLength
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-24 11:24:13 +00:00
|
|
|
void Accessors::FunctionLengthGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-24 11:24:13 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
2013-02-27 13:22:29 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
2014-04-24 11:24:13 +00:00
|
|
|
|
|
|
|
int length = 0;
|
2014-07-23 20:11:33 +00:00
|
|
|
if (function->shared()->is_compiled()) {
|
|
|
|
length = function->shared()->length();
|
|
|
|
} else {
|
|
|
|
// If the function isn't compiled yet, the length is not computed
|
|
|
|
// correctly yet. Compile it now and return the right length.
|
2015-08-24 06:52:46 +00:00
|
|
|
if (Compiler::Compile(function, KEEP_EXCEPTION)) {
|
2014-04-24 11:24:13 +00:00
|
|
|
length = function->shared()->length();
|
2014-07-23 20:11:33 +00:00
|
|
|
}
|
|
|
|
if (isolate->has_pending_exception()) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
2014-04-24 11:24:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Handle<Object> result(Smi::FromInt(length), isolate);
|
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-13 17:19:40 +00:00
|
|
|
MUST_USE_RESULT static MaybeHandle<Object> ReplaceAccessorWithDataProperty(
|
|
|
|
Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
|
|
|
|
Handle<Object> value, bool is_observed, Handle<Object> old_value) {
|
|
|
|
LookupIterator it(object, name);
|
|
|
|
CHECK_EQ(LookupIterator::ACCESSOR, it.state());
|
|
|
|
DCHECK(it.HolderIsReceiverOrHiddenPrototype());
|
|
|
|
it.ReconfigureDataProperty(value, it.property_details().attributes());
|
|
|
|
|
|
|
|
if (is_observed && !old_value->SameValue(*value)) {
|
|
|
|
return JSObject::EnqueueChangeRecord(object, "update", name, old_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MUST_USE_RESULT static MaybeHandle<Object> SetFunctionLength(
|
|
|
|
Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
|
|
|
|
Handle<Object> old_value;
|
|
|
|
bool is_observed = function->map()->is_observed();
|
|
|
|
if (is_observed) {
|
|
|
|
old_value = handle(Smi::FromInt(function->shared()->length()), isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ReplaceAccessorWithDataProperty(isolate, function,
|
|
|
|
isolate->factory()->length_string(),
|
|
|
|
value, is_observed, old_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 11:24:13 +00:00
|
|
|
void Accessors::FunctionLengthSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-24 11:24:13 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
2015-03-13 17:19:40 +00:00
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Handle<Object> value = Utils::OpenHandle(*val);
|
|
|
|
|
|
|
|
Handle<JSFunction> object =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
|
|
|
if (SetFunctionLength(isolate, object, value).is_null()) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
}
|
2014-04-24 11:24:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::FunctionLengthInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->length_string(),
|
|
|
|
&FunctionLengthGetter,
|
|
|
|
&FunctionLengthSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::FunctionName
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-04-28 08:26:35 +00:00
|
|
|
void Accessors::FunctionNameGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 08:26:35 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
2015-09-30 19:19:57 +00:00
|
|
|
Handle<Object> result;
|
|
|
|
if (function->shared()->name_should_print_as_anonymous()) {
|
|
|
|
result = isolate->factory()->anonymous_string();
|
|
|
|
} else {
|
|
|
|
result = handle(function->shared()->name(), isolate);
|
|
|
|
}
|
2014-04-28 08:26:35 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-04 16:56:55 +00:00
|
|
|
MUST_USE_RESULT static MaybeHandle<Object> SetFunctionName(
|
|
|
|
Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
|
|
|
|
Handle<Object> old_value;
|
|
|
|
bool is_observed = function->map()->is_observed();
|
|
|
|
if (is_observed) {
|
|
|
|
old_value = handle(function->shared()->name(), isolate);
|
|
|
|
}
|
|
|
|
|
2015-03-13 17:19:40 +00:00
|
|
|
return ReplaceAccessorWithDataProperty(isolate, function,
|
|
|
|
isolate->factory()->name_string(),
|
|
|
|
value, is_observed, old_value);
|
2015-03-04 16:56:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 08:26:35 +00:00
|
|
|
void Accessors::FunctionNameSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 08:26:35 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
2015-03-04 16:56:55 +00:00
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
Handle<Object> value = Utils::OpenHandle(*val);
|
|
|
|
|
|
|
|
Handle<JSFunction> object =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
|
|
|
if (SetFunctionName(isolate, object, value).is_null()) {
|
|
|
|
isolate->OptionalRescheduleException(false);
|
|
|
|
}
|
2014-04-28 08:26:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::FunctionNameInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->name_string(),
|
|
|
|
&FunctionNameGetter,
|
|
|
|
&FunctionNameSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::FunctionArguments
|
|
|
|
//
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2014-04-24 14:23:15 +00:00
|
|
|
static Handle<Object> ArgumentsForInlinedFunction(
|
2010-12-07 11:31:57 +00:00
|
|
|
JavaScriptFrame* frame,
|
|
|
|
Handle<JSFunction> inlined_function,
|
|
|
|
int inlined_frame_index) {
|
2013-02-25 14:46:09 +00:00
|
|
|
Isolate* isolate = inlined_function->GetIsolate();
|
|
|
|
Factory* factory = isolate->factory();
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
TranslatedState translated_values(frame);
|
|
|
|
translated_values.Prepare(false, frame->fp());
|
|
|
|
|
|
|
|
int argument_count = 0;
|
|
|
|
TranslatedFrame* translated_frame =
|
|
|
|
translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
|
|
|
|
&argument_count);
|
|
|
|
TranslatedFrame::iterator iter = translated_frame->begin();
|
|
|
|
|
2015-06-10 11:52:35 +00:00
|
|
|
// Skip the function.
|
|
|
|
iter++;
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
// Skip the receiver.
|
|
|
|
iter++;
|
|
|
|
argument_count--;
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
Handle<JSObject> arguments =
|
2015-06-08 10:04:51 +00:00
|
|
|
factory->NewArgumentsObject(inlined_function, argument_count);
|
|
|
|
Handle<FixedArray> array = factory->NewFixedArray(argument_count);
|
|
|
|
bool should_deoptimize = false;
|
|
|
|
for (int i = 0; i < argument_count; ++i) {
|
|
|
|
// If we materialize any object, we should deopt because we might alias
|
|
|
|
// an object that was eliminated by escape analysis.
|
|
|
|
should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
|
|
|
|
Handle<Object> value = iter->GetValue();
|
2010-12-07 11:31:57 +00:00
|
|
|
array->set(i, *value);
|
2015-06-08 10:04:51 +00:00
|
|
|
iter++;
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
arguments->set_elements(*array);
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
if (should_deoptimize) {
|
|
|
|
translated_values.StoreMaterializedValuesAndDeopt();
|
|
|
|
}
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// Return the freshly allocated arguments object.
|
2014-04-24 14:23:15 +00:00
|
|
|
return arguments;
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-04-24 14:23:15 +00:00
|
|
|
static int FindFunctionInFrame(JavaScriptFrame* frame,
|
|
|
|
Handle<JSFunction> function) {
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
List<JSFunction*> functions(2);
|
|
|
|
frame->GetFunctions(&functions);
|
|
|
|
for (int i = functions.length() - 1; i >= 0; i--) {
|
|
|
|
if (functions[i] == *function) return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<Object> GetFunctionArguments(Isolate* isolate,
|
|
|
|
Handle<JSFunction> function) {
|
|
|
|
if (function->shared()->native()) return isolate->factory()->null_value();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Find the top invocation of the function by traversing frames.
|
Simplify isolates access during stack iteration (WAS: Move SafeStackFrameIterator::active_count_...)
While trying to fix Mac and Windows versions for this change:
http://codereview.chromium.org/6771047/, I figured out, that we
already store an isolate in StackFrameIterator, so we can use it in
frame objects, instead of requiring it from caller.
I've changed iterators usage to the following scheme: whenever a
caller maintains an isolate pointer, it just passes it to stack
iterator, and no more worries about passing it to frame content
accessors. If a caller uses current isolate, it can omit passing it
to iterator, in this case, an iterator will use the current isolate,
too.
There was a special case with LiveEdit, which creates
detached copies of frame objects.
R=vitalyr@chromium.org
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6794019
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7499 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2011-04-05 09:01:47 +00:00
|
|
|
for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
|
2008-07-03 15:10:15 +00:00
|
|
|
JavaScriptFrame* frame = it.frame();
|
2014-04-24 14:23:15 +00:00
|
|
|
int function_index = FindFunctionInFrame(frame, function);
|
|
|
|
if (function_index < 0) continue;
|
|
|
|
|
|
|
|
if (function_index > 0) {
|
|
|
|
// The function in question was inlined. Inlined functions have the
|
|
|
|
// correct number of arguments and no allocated arguments object, so
|
|
|
|
// we can construct a fresh one by interpreting the function's
|
|
|
|
// deoptimization input data.
|
|
|
|
return ArgumentsForInlinedFunction(frame, function, function_index);
|
|
|
|
}
|
2011-02-02 15:08:29 +00:00
|
|
|
|
2015-11-04 10:35:46 +00:00
|
|
|
// Find the frame that holds the actual arguments passed to the function.
|
2014-04-24 14:23:15 +00:00
|
|
|
it.AdvanceToArgumentsFrame();
|
|
|
|
frame = it.frame();
|
|
|
|
|
|
|
|
// Get the number of arguments and construct an arguments object
|
|
|
|
// mirror for the right frame.
|
|
|
|
const int length = frame->ComputeParametersCount();
|
|
|
|
Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
|
|
|
|
function, length);
|
|
|
|
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
|
|
|
|
|
|
|
|
// Copy the parameters to the arguments object.
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(array->length() == length);
|
2014-04-24 14:23:15 +00:00
|
|
|
for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
|
|
|
|
arguments->set_elements(*array);
|
|
|
|
|
|
|
|
// Return the freshly allocated arguments object.
|
|
|
|
return arguments;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// No frame corresponding to the given function found. Return null.
|
2014-04-24 14:23:15 +00:00
|
|
|
return isolate->factory()->null_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
|
|
|
|
return GetFunctionArguments(function->GetIsolate(), function);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 12:02:11 +00:00
|
|
|
void Accessors::FunctionArgumentsGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 12:02:11 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
2014-04-24 14:23:15 +00:00
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
|
|
|
Handle<Object> result = GetFunctionArguments(isolate, function);
|
2014-04-28 12:02:11 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 12:02:11 +00:00
|
|
|
void Accessors::FunctionArgumentsSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 12:02:11 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
2014-07-24 16:42:54 +00:00
|
|
|
// Function arguments is non writable, non configurable.
|
|
|
|
UNREACHABLE();
|
2014-04-28 12:02:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->arguments_string(),
|
|
|
|
&FunctionArgumentsGetter,
|
|
|
|
&FunctionArgumentsSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Accessors::FunctionCaller
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2014-05-19 13:45:45 +00:00
|
|
|
static inline bool AllowAccessToFunction(Context* current_context,
|
|
|
|
JSFunction* function) {
|
|
|
|
return current_context->HasSameSecurityTokenAs(function->context());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-25 13:38:58 +00:00
|
|
|
class FrameFunctionIterator {
|
|
|
|
public:
|
2013-06-03 15:32:22 +00:00
|
|
|
FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
|
2014-05-19 13:45:45 +00:00
|
|
|
: isolate_(isolate),
|
|
|
|
frame_iterator_(isolate),
|
2011-08-25 13:38:58 +00:00
|
|
|
functions_(2),
|
|
|
|
index_(0) {
|
|
|
|
GetFunctions();
|
|
|
|
}
|
|
|
|
JSFunction* next() {
|
2014-05-19 13:45:45 +00:00
|
|
|
while (true) {
|
|
|
|
if (functions_.length() == 0) return NULL;
|
|
|
|
JSFunction* next_function = functions_[index_];
|
|
|
|
index_--;
|
|
|
|
if (index_ < 0) {
|
|
|
|
GetFunctions();
|
|
|
|
}
|
|
|
|
// Skip functions from other origins.
|
|
|
|
if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
|
|
|
|
return next_function;
|
2011-08-25 13:38:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterate through functions until the first occurence of 'function'.
|
|
|
|
// Returns true if 'function' is found, and false if the iterator ends
|
|
|
|
// without finding it.
|
|
|
|
bool Find(JSFunction* function) {
|
|
|
|
JSFunction* next_function;
|
|
|
|
do {
|
|
|
|
next_function = next();
|
|
|
|
if (next_function == function) return true;
|
|
|
|
} while (next_function != NULL);
|
|
|
|
return false;
|
|
|
|
}
|
2011-09-08 19:57:14 +00:00
|
|
|
|
2011-08-25 13:38:58 +00:00
|
|
|
private:
|
|
|
|
void GetFunctions() {
|
|
|
|
functions_.Rewind(0);
|
|
|
|
if (frame_iterator_.done()) return;
|
|
|
|
JavaScriptFrame* frame = frame_iterator_.frame();
|
|
|
|
frame->GetFunctions(&functions_);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(functions_.length() > 0);
|
2011-08-25 13:38:58 +00:00
|
|
|
frame_iterator_.Advance();
|
|
|
|
index_ = functions_.length() - 1;
|
|
|
|
}
|
2014-05-19 13:45:45 +00:00
|
|
|
Isolate* isolate_;
|
2011-08-25 13:38:58 +00:00
|
|
|
JavaScriptFrameIterator frame_iterator_;
|
|
|
|
List<JSFunction*> functions_;
|
|
|
|
int index_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-04-28 13:41:12 +00:00
|
|
|
MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
|
|
|
|
Handle<JSFunction> function) {
|
2013-06-03 15:32:22 +00:00
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
FrameFunctionIterator it(isolate, no_allocation);
|
2014-04-28 13:41:12 +00:00
|
|
|
if (function->shared()->native()) {
|
|
|
|
return MaybeHandle<JSFunction>();
|
|
|
|
}
|
2011-08-25 13:38:58 +00:00
|
|
|
// Find the function from the frames.
|
|
|
|
if (!it.Find(*function)) {
|
|
|
|
// No frame corresponding to the given function found. Return null.
|
2014-04-28 13:41:12 +00:00
|
|
|
return MaybeHandle<JSFunction>();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
2011-08-25 13:38:58 +00:00
|
|
|
// Find previously called non-toplevel function.
|
|
|
|
JSFunction* caller;
|
|
|
|
do {
|
|
|
|
caller = it.next();
|
2014-04-28 13:41:12 +00:00
|
|
|
if (caller == NULL) return MaybeHandle<JSFunction>();
|
2011-08-25 13:38:58 +00:00
|
|
|
} while (caller->shared()->is_toplevel());
|
|
|
|
|
|
|
|
// If caller is a built-in function and caller's caller is also built-in,
|
|
|
|
// use that instead.
|
|
|
|
JSFunction* potential_caller = caller;
|
2015-11-04 14:56:11 +00:00
|
|
|
while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) {
|
2011-08-25 13:38:58 +00:00
|
|
|
caller = potential_caller;
|
|
|
|
potential_caller = it.next();
|
|
|
|
}
|
2012-09-05 08:19:49 +00:00
|
|
|
if (!caller->shared()->native() && potential_caller != NULL) {
|
|
|
|
caller = potential_caller;
|
|
|
|
}
|
2014-03-11 14:39:08 +00:00
|
|
|
// Censor if the caller is not a sloppy mode function.
|
2012-11-23 15:47:58 +00:00
|
|
|
// Change from ES5, which used to throw, see:
|
|
|
|
// https://bugs.ecmascript.org/show_bug.cgi?id=310
|
2015-02-04 09:34:05 +00:00
|
|
|
if (is_strict(caller->shared()->language_mode())) {
|
2014-04-28 13:41:12 +00:00
|
|
|
return MaybeHandle<JSFunction>();
|
|
|
|
}
|
2014-05-19 13:45:45 +00:00
|
|
|
// Don't return caller from another security context.
|
|
|
|
if (!AllowAccessToFunction(isolate->context(), caller)) {
|
|
|
|
return MaybeHandle<JSFunction>();
|
|
|
|
}
|
2014-04-28 13:41:12 +00:00
|
|
|
return Handle<JSFunction>(caller);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Accessors::FunctionCallerGetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 13:41:12 +00:00
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
|
|
|
HandleScope scope(isolate);
|
2014-07-23 20:11:33 +00:00
|
|
|
Handle<JSFunction> function =
|
|
|
|
Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
|
2014-04-28 13:41:12 +00:00
|
|
|
Handle<Object> result;
|
2014-07-23 20:11:33 +00:00
|
|
|
MaybeHandle<JSFunction> maybe_caller;
|
|
|
|
maybe_caller = FindCaller(isolate, function);
|
|
|
|
Handle<JSFunction> caller;
|
|
|
|
if (maybe_caller.ToHandle(&caller)) {
|
|
|
|
result = caller;
|
2014-04-28 13:41:12 +00:00
|
|
|
} else {
|
2014-07-23 20:11:33 +00:00
|
|
|
result = isolate->factory()->null_value();
|
2012-11-23 15:47:58 +00:00
|
|
|
}
|
2014-04-28 13:41:12 +00:00
|
|
|
info.GetReturnValue().Set(Utils::ToLocal(result));
|
|
|
|
}
|
|
|
|
|
2012-11-23 15:47:58 +00:00
|
|
|
|
2014-04-28 13:41:12 +00:00
|
|
|
void Accessors::FunctionCallerSetter(
|
2014-08-20 15:25:13 +00:00
|
|
|
v8::Local<v8::Name> name,
|
2014-04-28 13:41:12 +00:00
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
2014-07-24 16:42:54 +00:00
|
|
|
// Function caller is non writable, non configurable.
|
|
|
|
UNREACHABLE();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 13:41:12 +00:00
|
|
|
Handle<AccessorInfo> Accessors::FunctionCallerInfo(
|
|
|
|
Isolate* isolate, PropertyAttributes attributes) {
|
|
|
|
return MakeAccessor(isolate,
|
|
|
|
isolate->factory()->caller_string(),
|
|
|
|
&FunctionCallerGetter,
|
|
|
|
&FunctionCallerSetter,
|
|
|
|
attributes);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
2012-07-09 08:59:03 +00:00
|
|
|
//
|
|
|
|
// Accessors::MakeModuleExport
|
|
|
|
//
|
|
|
|
|
2016-01-18 18:48:02 +00:00
|
|
|
static void ModuleGetExport(v8::Local<v8::Name> property,
|
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
2012-07-09 08:59:03 +00:00
|
|
|
JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
|
|
|
|
Context* context = Context::cast(instance->context());
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(context->IsModuleContext());
|
2013-02-25 14:46:09 +00:00
|
|
|
Isolate* isolate = instance->GetIsolate();
|
2015-06-03 10:27:46 +00:00
|
|
|
int slot = info.Data()
|
|
|
|
->Int32Value(info.GetIsolate()->GetCurrentContext())
|
|
|
|
.FromMaybe(-1);
|
|
|
|
if (slot < 0 || slot >= context->length()) {
|
2016-01-18 18:48:02 +00:00
|
|
|
Handle<Name> name = v8::Utils::OpenHandle(*property);
|
2015-06-03 10:27:46 +00:00
|
|
|
|
|
|
|
Handle<Object> exception = isolate->factory()->NewReferenceError(
|
|
|
|
MessageTemplate::kNotDefined, name);
|
|
|
|
isolate->ScheduleThrow(*exception);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Object* value = context->get(slot);
|
2012-07-09 08:59:03 +00:00
|
|
|
if (value->IsTheHole()) {
|
2016-01-18 18:48:02 +00:00
|
|
|
Handle<Name> name = v8::Utils::OpenHandle(*property);
|
2014-09-01 09:11:44 +00:00
|
|
|
|
2015-02-24 09:01:33 +00:00
|
|
|
Handle<Object> exception = isolate->factory()->NewReferenceError(
|
2015-05-07 10:00:21 +00:00
|
|
|
MessageTemplate::kNotDefined, name);
|
2014-09-01 09:11:44 +00:00
|
|
|
isolate->ScheduleThrow(*exception);
|
2013-06-05 12:36:33 +00:00
|
|
|
return;
|
2012-07-09 08:59:03 +00:00
|
|
|
}
|
2013-06-05 12:36:33 +00:00
|
|
|
info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
|
2012-07-09 08:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-18 18:48:02 +00:00
|
|
|
static void ModuleSetExport(v8::Local<v8::Name> property,
|
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
2016-01-22 09:53:29 +00:00
|
|
|
if (!info.ShouldThrowOnError()) return;
|
2016-01-18 18:48:02 +00:00
|
|
|
Handle<Name> name = v8::Utils::OpenHandle(*property);
|
|
|
|
Isolate* isolate = name->GetIsolate();
|
|
|
|
Handle<Object> exception =
|
|
|
|
isolate->factory()->NewTypeError(MessageTemplate::kNotDefined, name);
|
|
|
|
isolate->ScheduleThrow(*exception);
|
2012-07-09 08:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<AccessorInfo> Accessors::MakeModuleExport(
|
|
|
|
Handle<String> name,
|
|
|
|
int index,
|
|
|
|
PropertyAttributes attributes) {
|
2013-09-02 09:27:27 +00:00
|
|
|
Isolate* isolate = name->GetIsolate();
|
2016-01-18 18:48:02 +00:00
|
|
|
Handle<AccessorInfo> info = MakeAccessor(isolate, name, &ModuleGetExport,
|
|
|
|
&ModuleSetExport, attributes);
|
2012-07-09 08:59:03 +00:00
|
|
|
info->set_data(Smi::FromInt(index));
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-01 22:46:54 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|