Version 2.2.12
Allowed accessors to be defined on objects rather than just object templates.
Changed the ScriptData API.
git-svn-id: http://v8.googlecode.com/svn/trunk@4730 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index d7b05cf..eb555d7 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -356,7 +356,7 @@
Register holder,
Register scratch1,
Register scratch2,
- JSObject* holder_obj,
+ JSObject* interceptor_holder,
LookupResult* lookup,
String* name,
Label* miss_label) {
@@ -376,7 +376,8 @@
}
if (!optimize) {
- CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
+ CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
+ miss_label);
return;
}
@@ -389,12 +390,17 @@
__ push(holder);
__ push(name_);
+ // Invoke an interceptor. Note: map checks from receiver to
+ // interceptor's holder has been compiled before (see a caller
+ // of this method.)
CompileCallLoadPropertyWithInterceptor(masm,
receiver,
holder,
name_,
- holder_obj);
+ interceptor_holder);
+ // Check if interceptor provided a value for property. If it's
+ // the case, return immediately.
Label interceptor_failed;
__ cmp(eax, Factory::no_interceptor_result_sentinel());
__ j(equal, &interceptor_failed);
@@ -411,47 +417,61 @@
__ LeaveInternalFrame();
if (lookup->type() == FIELD) {
- holder = stub_compiler->CheckPrototypes(holder_obj, holder,
+ // We found FIELD property in prototype chain of interceptor's holder.
+ // Check that the maps from interceptor's holder to field's holder
+ // haven't changed...
+ holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
lookup->holder(), scratch1,
scratch2,
name,
miss_label);
+ // ... and retrieve a field from field's holder.
stub_compiler->GenerateFastPropertyLoad(masm, eax,
holder, lookup->holder(),
lookup->GetFieldIndex());
__ ret(0);
} else {
+ // We found CALLBACKS property in prototype chain of interceptor's
+ // holder.
ASSERT(lookup->type() == CALLBACKS);
ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
ASSERT(callback != NULL);
ASSERT(callback->getter() != NULL);
+ // Prepare for tail call: push receiver to stack after return address.
Label cleanup;
- __ pop(scratch2);
+ __ pop(scratch2); // return address
__ push(receiver);
__ push(scratch2);
- holder = stub_compiler->CheckPrototypes(holder_obj, holder,
+ // Check that the maps from interceptor's holder to callback's holder
+ // haven't changed.
+ holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
lookup->holder(), scratch1,
scratch2,
name,
&cleanup);
- __ pop(scratch2); // save old return address
+ // Continue tail call preparation: push remaining parameters after
+ // return address.
+ __ pop(scratch2); // return address
__ push(holder);
__ mov(holder, Immediate(Handle<AccessorInfo>(callback)));
__ push(holder);
__ push(FieldOperand(holder, AccessorInfo::kDataOffset));
__ push(name_);
- __ push(scratch2); // restore old return address
+ __ push(scratch2); // restore return address
+ // Tail call to runtime.
ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallExternalReference(ref, 5, 1);
+ // Clean up code: we pushed receiver after return address and
+ // need to remove it from there.
__ bind(&cleanup);
- __ pop(scratch1);
- __ pop(scratch2);
+ __ pop(scratch1); // return address.
+ __ pop(scratch2); // receiver.
__ push(scratch1);
}
}
@@ -461,10 +481,10 @@
Register receiver,
Register holder,
Register scratch,
- JSObject* holder_obj,
+ JSObject* interceptor_holder,
Label* miss_label) {
__ pop(scratch); // save old return address
- PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
+ PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
__ push(scratch); // restore old return address
ExternalReference ref = ExternalReference(
@@ -626,7 +646,7 @@
Register receiver,
Register scratch1,
Register scratch2,
- JSObject* holder_obj,
+ JSObject* interceptor_holder,
LookupResult* lookup,
String* name,
const CallOptimization& optimization,
@@ -639,10 +659,13 @@
bool can_do_fast_api_call = false;
if (optimization.is_simple_api_call() &&
!lookup->holder()->IsGlobalObject()) {
- depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj);
+ depth1 =
+ optimization.GetPrototypeDepthOfExpectedType(object,
+ interceptor_holder);
if (depth1 == kInvalidProtoDepth) {
- depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj,
- lookup->holder());
+ depth2 =
+ optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
+ lookup->holder());
}
can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
(depth2 != kInvalidProtoDepth);
@@ -655,24 +678,32 @@
ReserveSpaceForFastApiCall(masm, scratch1);
}
+ // Check that the maps from receiver to interceptor's holder
+ // haven't changed and thus we can invoke interceptor.
Label miss_cleanup;
Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
Register holder =
- stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
+ stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
scratch1, scratch2, name,
depth1, miss);
+ // Invoke an interceptor and if it provides a value,
+ // branch to |regular_invoke|.
Label regular_invoke;
- LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke);
+ LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
+ ®ular_invoke);
- // Generate code for the failed interceptor case.
+ // Interceptor returned nothing for this property. Try to use cached
+ // constant function.
- // Check the lookup is still valid.
- stub_compiler_->CheckPrototypes(holder_obj, receiver,
+ // Check that the maps from interceptor's holder to constant function's
+ // holder haven't changed and thus we can use cached constant function.
+ stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
lookup->holder(),
scratch1, scratch2, name,
depth2, miss);
+ // Invoke function.
if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else {
@@ -680,12 +711,14 @@
JUMP_FUNCTION);
}
+ // Deferred code for fast API call case---clean preallocated space.
if (can_do_fast_api_call) {
__ bind(&miss_cleanup);
FreeSpaceForFastApiCall(masm, scratch1);
__ jmp(miss_label);
}
+ // Invoke a regular function.
__ bind(®ular_invoke);
if (can_do_fast_api_call) {
FreeSpaceForFastApiCall(masm, scratch1);
@@ -698,10 +731,10 @@
Register scratch1,
Register scratch2,
String* name,
- JSObject* holder_obj,
+ JSObject* interceptor_holder,
Label* miss_label) {
Register holder =
- stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
+ stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
scratch1, scratch2, name,
miss_label);
@@ -713,7 +746,7 @@
receiver,
holder,
name_,
- holder_obj);
+ interceptor_holder);
__ CallExternalReference(
ExternalReference(