Commit e14402b1 authored by rossberg@chromium.org's avatar rossberg@chromium.org

A first skeleton for introducing Harmony proxies.

1) Add new type JSProxy for representing proxy objects.
   Currently devoid of functionality, i.e., all properties are undefined.

2) Some rudimentary global $Proxy functions to create proxies.

Next step: Hook up getProperty and getOwnProperty handlers. Will probably
require introducing a new LookupResult type, which is a mixture of
INTERCEPTOR (handles any property) and CALLBACK (calls back to JS).
Can we unify this somehow?

TODO: Should probably rename existing Proxy type to something like
"Foreign", to avoid confusion.

Review URL: http://codereview.chromium.org/6932068

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7887 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent edac3d93
...@@ -3682,7 +3682,7 @@ class Internals { ...@@ -3682,7 +3682,7 @@ class Internals {
static const int kFullStringRepresentationMask = 0x07; static const int kFullStringRepresentationMask = 0x07;
static const int kExternalTwoByteRepresentationTag = 0x02; static const int kExternalTwoByteRepresentationTag = 0x02;
static const int kJSObjectType = 0xa1; static const int kJSObjectType = 0xa2;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kProxyType = 0x85; static const int kProxyType = 0x85;
......
...@@ -1638,10 +1638,12 @@ bool Genesis::InstallNatives() { ...@@ -1638,10 +1638,12 @@ bool Genesis::InstallNatives() {
bool Genesis::InstallExperimentalNatives() { bool Genesis::InstallExperimentalNatives() {
if (FLAG_harmony_proxies) { for (int i = ExperimentalNatives::GetDebuggerCount();
for (int i = ExperimentalNatives::GetDebuggerCount(); i < ExperimentalNatives::GetBuiltinsCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {
i++) { if (FLAG_harmony_proxies &&
strcmp(ExperimentalNatives::GetScriptName(i).start(),
"native proxy.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false; if (!CompileExperimentalBuiltin(isolate(), i)) return false;
} }
} }
......
...@@ -832,6 +832,15 @@ Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements, ...@@ -832,6 +832,15 @@ Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
} }
Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
Handle<Object> prototype) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateJSProxy(*handler, *prototype),
JSProxy);
}
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo( Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name, Handle<String> name,
int number_of_literals, int number_of_literals,
......
...@@ -231,6 +231,8 @@ class Factory { ...@@ -231,6 +231,8 @@ class Factory {
Handle<FixedArray> elements, Handle<FixedArray> elements,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
Handle<JSFunction> NewFunction(Handle<String> name, Handle<JSFunction> NewFunction(Handle<String> name,
Handle<Object> prototype); Handle<Object> prototype);
......
...@@ -3213,6 +3213,27 @@ MaybeObject* Heap::AllocateJSObject(JSFunction* constructor, ...@@ -3213,6 +3213,27 @@ MaybeObject* Heap::AllocateJSObject(JSFunction* constructor,
} }
MaybeObject* Heap::AllocateJSProxy(Object* handler, Object* prototype) {
// Allocate map.
// TODO(rossberg): Once we optimize proxies, think about a scheme to share
// maps. Will probably depend on the identity of the handler object, too.
Object* map_obj;
MaybeObject* maybe_map_obj = AllocateMap(JS_PROXY_TYPE, JSProxy::kSize);
if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj;
Map* map = Map::cast(map_obj);
map->set_prototype(prototype);
map->set_pre_allocated_property_fields(1);
map->set_inobject_properties(1);
// Allocate the proxy object.
Object* result;
MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
if (!maybe_result->ToObject(&result)) return maybe_result;
JSProxy::cast(result)->set_handler(handler);
return result;
}
MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) { MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
ASSERT(constructor->has_initial_map()); ASSERT(constructor->has_initial_map());
Map* map = constructor->initial_map(); Map* map = constructor->initial_map();
......
...@@ -452,6 +452,13 @@ class Heap { ...@@ -452,6 +452,13 @@ class Heap {
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateFunctionPrototype(JSFunction* function); MUST_USE_RESULT MaybeObject* AllocateFunctionPrototype(JSFunction* function);
// Allocates a Harmony Proxy.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateJSProxy(Object* handler,
Object* prototype);
// Reinitialize an JSGlobalProxy based on a constructor. The object // Reinitialize an JSGlobalProxy based on a constructor. The object
// must have the same size as objects allocated using the // must have the same size as objects allocated using the
// constructor. The object is reinitialized and behaves as an // constructor. The object is reinitialized and behaves as an
......
...@@ -80,8 +80,8 @@ class EntryFrameConstants : public AllStatic { ...@@ -80,8 +80,8 @@ class EntryFrameConstants : public AllStatic {
class ExitFrameConstants : public AllStatic { class ExitFrameConstants : public AllStatic {
public: public:
static const int kCodeOffset = -2 * kPointerSize; static const int kCodeOffset = -2 * kPointerSize;
static const int kSPOffset = -1 * kPointerSize; static const int kSPOffset = -1 * kPointerSize;
static const int kCallerFPOffset = 0 * kPointerSize; static const int kCallerFPOffset = 0 * kPointerSize;
static const int kCallerPCOffset = +1 * kPointerSize; static const int kCallerPCOffset = +1 * kPointerSize;
...@@ -94,7 +94,9 @@ class ExitFrameConstants : public AllStatic { ...@@ -94,7 +94,9 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
static const int kFixedFrameSize = 4; // StandardFrame::IterateExpressions assumes that kContextOffset is the last
// object pointer.
static const int kFixedFrameSize = 4; // Currently unused.
static const int kExpressionsOffset = -3 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
......
...@@ -155,6 +155,9 @@ void HeapObject::HeapObjectVerify() { ...@@ -155,6 +155,9 @@ void HeapObject::HeapObjectVerify() {
break; break;
case FILLER_TYPE: case FILLER_TYPE:
break; break;
case JS_PROXY_TYPE:
JSProxy::cast(this)->JSProxyVerify();
break;
case PROXY_TYPE: case PROXY_TYPE:
Proxy::cast(this)->ProxyVerify(); Proxy::cast(this)->ProxyVerify();
break; break;
...@@ -461,6 +464,11 @@ void JSRegExp::JSRegExpVerify() { ...@@ -461,6 +464,11 @@ void JSRegExp::JSRegExpVerify() {
} }
void JSProxy::JSProxyVerify() {
ASSERT(IsJSProxy());
VerifyPointer(handler());
}
void Proxy::ProxyVerify() { void Proxy::ProxyVerify() {
ASSERT(IsProxy()); ASSERT(IsProxy());
} }
......
...@@ -584,6 +584,12 @@ bool Object::IsStringWrapper() { ...@@ -584,6 +584,12 @@ bool Object::IsStringWrapper() {
} }
bool Object::IsJSProxy() {
return Object::IsHeapObject()
&& HeapObject::cast(this)->map()->instance_type() == JS_PROXY_TYPE;
}
bool Object::IsProxy() { bool Object::IsProxy() {
return Object::IsHeapObject() return Object::IsHeapObject()
&& HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE; && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
...@@ -1898,6 +1904,7 @@ CAST_ACCESSOR(JSBuiltinsObject) ...@@ -1898,6 +1904,7 @@ CAST_ACCESSOR(JSBuiltinsObject)
CAST_ACCESSOR(Code) CAST_ACCESSOR(Code)
CAST_ACCESSOR(JSArray) CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSRegExp) CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(Proxy) CAST_ACCESSOR(Proxy)
CAST_ACCESSOR(ByteArray) CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(ExternalArray) CAST_ACCESSOR(ExternalArray)
...@@ -3521,6 +3528,9 @@ void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id, ...@@ -3521,6 +3528,9 @@ void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
} }
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Address Proxy::proxy() { Address Proxy::proxy() {
return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset)); return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
} }
......
...@@ -148,6 +148,9 @@ void HeapObject::HeapObjectPrint(FILE* out) { ...@@ -148,6 +148,9 @@ void HeapObject::HeapObjectPrint(FILE* out) {
case CODE_TYPE: case CODE_TYPE:
Code::cast(this)->CodePrint(out); Code::cast(this)->CodePrint(out);
break; break;
case JS_PROXY_TYPE:
JSProxy::cast(this)->JSProxyPrint(out);
break;
case PROXY_TYPE: case PROXY_TYPE:
Proxy::cast(this)->ProxyPrint(out); Proxy::cast(this)->ProxyPrint(out);
break; break;
...@@ -408,6 +411,7 @@ static const char* TypeToString(InstanceType type) { ...@@ -408,6 +411,7 @@ static const char* TypeToString(InstanceType type) {
case JS_FUNCTION_TYPE: return "JS_FUNCTION"; case JS_FUNCTION_TYPE: return "JS_FUNCTION";
case CODE_TYPE: return "CODE"; case CODE_TYPE: return "CODE";
case JS_ARRAY_TYPE: return "JS_ARRAY"; case JS_ARRAY_TYPE: return "JS_ARRAY";
case JS_PROXY_TYPE: return "JS_PROXY";
case JS_REGEXP_TYPE: return "JS_REGEXP"; case JS_REGEXP_TYPE: return "JS_REGEXP";
case JS_VALUE_TYPE: return "JS_VALUE"; case JS_VALUE_TYPE: return "JS_VALUE";
case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT"; case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
...@@ -530,6 +534,15 @@ void String::StringPrint(FILE* out) { ...@@ -530,6 +534,15 @@ void String::StringPrint(FILE* out) {
} }
void JSProxy::JSProxyPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSProxy");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
PrintF(out, "\n");
}
void JSFunction::JSFunctionPrint(FILE* out) { void JSFunction::JSFunctionPrint(FILE* out) {
HeapObject::PrintHeader(out, "Function"); HeapObject::PrintHeader(out, "Function");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map())); PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
......
...@@ -88,6 +88,11 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -88,6 +88,11 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case SHARED_FUNCTION_INFO_TYPE: case SHARED_FUNCTION_INFO_TYPE:
return kVisitSharedFunctionInfo; return kVisitSharedFunctionInfo;
case JS_PROXY_TYPE:
return GetVisitorIdForSize(kVisitDataObject,
kVisitDataObjectGeneric,
JSProxy::kSize);
case PROXY_TYPE: case PROXY_TYPE:
return GetVisitorIdForSize(kVisitDataObject, return GetVisitorIdForSize(kVisitDataObject,
kVisitDataObjectGeneric, kVisitDataObjectGeneric,
......
...@@ -134,24 +134,22 @@ Object* Object::ToBoolean() { ...@@ -134,24 +134,22 @@ Object* Object::ToBoolean() {
void Object::Lookup(String* name, LookupResult* result) { void Object::Lookup(String* name, LookupResult* result) {
Object* holder = NULL; Object* holder = NULL;
if (IsSmi()) { if (IsSmi()) {
Heap* heap = Isolate::Current()->heap(); Context* global_context = Isolate::Current()->context()->global_context();
Context* global_context = heap->isolate()->context()->global_context();
holder = global_context->number_function()->instance_prototype(); holder = global_context->number_function()->instance_prototype();
} else { } else {
HeapObject* heap_object = HeapObject::cast(this); HeapObject* heap_object = HeapObject::cast(this);
if (heap_object->IsJSObject()) { if (heap_object->IsJSObject()) {
return JSObject::cast(this)->Lookup(name, result); return JSObject::cast(this)->Lookup(name, result);
} }
Heap* heap = heap_object->GetHeap(); Context* global_context = Isolate::Current()->context()->global_context();
if (heap_object->IsString()) { if (heap_object->IsString()) {
Context* global_context = heap->isolate()->context()->global_context();
holder = global_context->string_function()->instance_prototype(); holder = global_context->string_function()->instance_prototype();
} else if (heap_object->IsHeapNumber()) { } else if (heap_object->IsHeapNumber()) {
Context* global_context = heap->isolate()->context()->global_context();
holder = global_context->number_function()->instance_prototype(); holder = global_context->number_function()->instance_prototype();
} else if (heap_object->IsBoolean()) { } else if (heap_object->IsBoolean()) {
Context* global_context = heap->isolate()->context()->global_context();
holder = global_context->boolean_function()->instance_prototype(); holder = global_context->boolean_function()->instance_prototype();
} else if (heap_object->IsJSProxy()) {
return result->NotFound(); // For now...
} }
} }
ASSERT(holder != NULL); // Cannot handle null or undefined. ASSERT(holder != NULL); // Cannot handle null or undefined.
...@@ -494,12 +492,13 @@ MaybeObject* Object::GetProperty(Object* receiver, ...@@ -494,12 +492,13 @@ MaybeObject* Object::GetProperty(Object* receiver,
Heap* heap = name->GetHeap(); Heap* heap = name->GetHeap();
// Traverse the prototype chain from the current object (this) to // Traverse the prototype chain from the current object (this) to
// the holder and check for access rights. This avoid traversing the // the holder and check for access rights. This avoids traversing the
// objects more than once in case of interceptors, because the // objects more than once in case of interceptors, because the
// holder will always be the interceptor holder and the search may // holder will always be the interceptor holder and the search may
// only continue with a current object just after the interceptor // only continue with a current object just after the interceptor
// holder in the prototype chain. // holder in the prototype chain.
Object* last = result->IsProperty() ? result->holder() : heap->null_value(); Object* last = result->IsProperty() ? result->holder() : heap->null_value();
ASSERT(this != this->GetPrototype());
for (Object* current = this; true; current = current->GetPrototype()) { for (Object* current = this; true; current = current->GetPrototype()) {
if (current->IsAccessCheckNeeded()) { if (current->IsAccessCheckNeeded()) {
// Check if we're allowed to read from the current object. Note // Check if we're allowed to read from the current object. Note
...@@ -575,6 +574,8 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { ...@@ -575,6 +574,8 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
holder = global_context->number_function()->instance_prototype(); holder = global_context->number_function()->instance_prototype();
} else if (heap_object->IsBoolean()) { } else if (heap_object->IsBoolean()) {
holder = global_context->boolean_function()->instance_prototype(); holder = global_context->boolean_function()->instance_prototype();
} else if (heap_object->IsJSProxy()) {
return heap->undefined_value(); // For now...
} else { } else {
// Undefined and null have no indexed properties. // Undefined and null have no indexed properties.
ASSERT(heap_object->IsUndefined() || heap_object->IsNull()); ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
...@@ -595,9 +596,10 @@ Object* Object::GetPrototype() { ...@@ -595,9 +596,10 @@ Object* Object::GetPrototype() {
HeapObject* heap_object = HeapObject::cast(this); HeapObject* heap_object = HeapObject::cast(this);
// The object is either a number, a string, a boolean, or a real JS object. // The object is either a number, a string, a boolean,
if (heap_object->IsJSObject()) { // a real JS object, or a Harmony proxy.
return JSObject::cast(this)->map()->prototype(); if (heap_object->IsJSObject() || heap_object->IsJSProxy()) {
return heap_object->map()->prototype();
} }
Heap* heap = heap_object->GetHeap(); Heap* heap = heap_object->GetHeap();
Context* context = heap->isolate()->context()->global_context(); Context* context = heap->isolate()->context()->global_context();
...@@ -1154,6 +1156,9 @@ void HeapObject::IterateBody(InstanceType type, int object_size, ...@@ -1154,6 +1156,9 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case ODDBALL_TYPE: case ODDBALL_TYPE:
Oddball::BodyDescriptor::IterateBody(this, v); Oddball::BodyDescriptor::IterateBody(this, v);
break; break;
case JS_PROXY_TYPE:
JSProxy::BodyDescriptor::IterateBody(this, v);
break;
case PROXY_TYPE: case PROXY_TYPE:
reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v); reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
break; break;
......
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
// - Code // - Code
// - Map // - Map
// - Oddball // - Oddball
// - JSProxy
// - Proxy // - Proxy
// - SharedFunctionInfo // - SharedFunctionInfo
// - Struct // - Struct
...@@ -287,6 +288,7 @@ static const int kVariableSizeSentinel = 0; ...@@ -287,6 +288,7 @@ static const int kVariableSizeSentinel = 0;
V(JS_GLOBAL_PROPERTY_CELL_TYPE) \ V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
\ \
V(HEAP_NUMBER_TYPE) \ V(HEAP_NUMBER_TYPE) \
V(JS_PROXY_TYPE) \
V(PROXY_TYPE) \ V(PROXY_TYPE) \
V(BYTE_ARRAY_TYPE) \ V(BYTE_ARRAY_TYPE) \
/* Note: the order of these external array */ \ /* Note: the order of these external array */ \
...@@ -515,6 +517,7 @@ enum InstanceType { ...@@ -515,6 +517,7 @@ enum InstanceType {
// objects. // objects.
HEAP_NUMBER_TYPE, HEAP_NUMBER_TYPE,
PROXY_TYPE, PROXY_TYPE,
JS_PROXY_TYPE,
BYTE_ARRAY_TYPE, BYTE_ARRAY_TYPE,
EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
...@@ -720,6 +723,7 @@ class MaybeObject BASE_EMBEDDED { ...@@ -720,6 +723,7 @@ class MaybeObject BASE_EMBEDDED {
V(Proxy) \ V(Proxy) \
V(Boolean) \ V(Boolean) \
V(JSArray) \ V(JSArray) \
V(JSProxy) \
V(JSRegExp) \ V(JSRegExp) \
V(HashTable) \ V(HashTable) \
V(Dictionary) \ V(Dictionary) \
...@@ -3956,7 +3960,7 @@ class Map: public HeapObject { ...@@ -3956,7 +3960,7 @@ class Map: public HeapObject {
// An abstract superclass, a marker class really, for simple structure classes. // An abstract superclass, a marker class really, for simple structure classes.
// It doesn't carry much functionality but allows struct classes to me // It doesn't carry much functionality but allows struct classes to be
// identified in the type system. // identified in the type system.
class Struct: public HeapObject { class Struct: public HeapObject {
public: public:
...@@ -6103,6 +6107,39 @@ class JSGlobalPropertyCell: public HeapObject { ...@@ -6103,6 +6107,39 @@ class JSGlobalPropertyCell: public HeapObject {
}; };
// The JSProxy describes EcmaScript Harmony proxies
class JSProxy: public HeapObject {
public:
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
// Casting.
static inline JSProxy* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSProxyPrint() {
JSProxyPrint(stdout);
}
void JSProxyPrint(FILE* out);
#endif
#ifdef DEBUG
void JSProxyVerify();
#endif
// Layout description.
static const int kHandlerOffset = HeapObject::kHeaderSize;
static const int kSize = kHandlerOffset + kPointerSize;
typedef FixedBodyDescriptor<kHandlerOffset,
kHandlerOffset + kPointerSize,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
};
// Proxy describes objects pointing from JavaScript to C structures. // Proxy describes objects pointing from JavaScript to C structures.
// Since they cannot contain references to JS HeapObjects they can be // Since they cannot contain references to JS HeapObjects they can be
......
...@@ -26,3 +26,40 @@ ...@@ -26,3 +26,40 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
global.Proxy = new $Object(); global.Proxy = new $Object();
var $Proxy = global.Proxy
var fundamentalTraps = [
"getOwnPropertyDescriptor",
"getPropertyDescriptor",
"getOwnPropertyNames",
"getPropertyNames",
"defineProperty",
"delete",
"fix",
]
var derivedTraps = [
"has",
"hasOwn",
"get",
"set",
"enumerate",
"keys",
]
var functionTraps = [
"callTrap",
"constructTrap",
]
$Proxy.createFunction = function(handler, callTrap, constructTrap) {
handler.callTrap = callTrap
handler.constructTrap = constructTrap
$Proxy.create(handler)
}
$Proxy.create = function(handler, proto) {
if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
return %CreateJSProxy(handler, proto)
}
...@@ -588,6 +588,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { ...@@ -588,6 +588,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
} }
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
ASSERT(args.length() == 2);
Object* handler = args[0];
Object* prototype = args[1];
Object* used_prototype =
(prototype->IsJSObject() || prototype->IsJSProxy()) ? prototype
: isolate->heap()->null_value();
return isolate->heap()->AllocateJSProxy(handler, used_prototype);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCatchExtensionObject) { RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCatchExtensionObject) {
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CONVERT_CHECKED(String, key, args[0]); CONVERT_CHECKED(String, key, args[0]);
......
...@@ -275,6 +275,9 @@ namespace internal { ...@@ -275,6 +275,9 @@ namespace internal {
F(CreateArrayLiteral, 3, 1) \ F(CreateArrayLiteral, 3, 1) \
F(CreateArrayLiteralShallow, 3, 1) \ F(CreateArrayLiteralShallow, 3, 1) \
\ \
/* Harmony proxies */ \
F(CreateJSProxy, 2, 1) \
\
/* Catch context extension objects */ \ /* Catch context extension objects */ \
F(CreateCatchExtensionObject, 2, 1) \ F(CreateCatchExtensionObject, 2, 1) \
\ \
......
...@@ -644,6 +644,6 @@ function DefaultString(x) { ...@@ -644,6 +644,6 @@ function DefaultString(x) {
// NOTE: Setting the prototype for Array must take place as early as // NOTE: Setting the prototype for Array must take place as early as
// possible due to code generation for array literals. When // possible due to code generation for array literals. When
// generating code for a array literal a boilerplate array is created // generating code for a array literal a boilerplate array is created
// that is cloned when running the code. It is essiential that the // that is cloned when running the code. It is essential that the
// boilerplate gets the right prototype. // boilerplate gets the right prototype.
%FunctionSetPrototype($Array, new $Array(0)); %FunctionSetPrototype($Array, new $Array(0));
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