Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 2251003: Refactor GenerateLoadInterceptor, removing LoadInterceptorCompiler class and CompileLoadInterceptor (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 Register holder, 293 Register holder,
294 Register name, 294 Register name,
295 JSObject* holder_obj) { 295 JSObject* holder_obj) {
296 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 296 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
297 __ CallExternalReference( 297 __ CallExternalReference(
298 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)), 298 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
299 5); 299 5);
300 } 300 }
301 301
302 302
303 template <class Compiler>
304 static void CompileLoadInterceptor(Compiler* compiler,
305 StubCompiler* stub_compiler,
306 MacroAssembler* masm,
307 JSObject* object,
308 JSObject* holder,
309 String* name,
310 LookupResult* lookup,
311 Register receiver,
312 Register scratch1,
313 Register scratch2,
314 Label* miss) {
315 ASSERT(holder->HasNamedInterceptor());
316 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
317
318 // Check that the receiver isn't a smi.
319 __ test(receiver, Immediate(kSmiTagMask));
320 __ j(zero, miss, not_taken);
321
322 // Check that the maps haven't changed.
323 Register reg =
324 stub_compiler->CheckPrototypes(object, receiver, holder,
325 scratch1, scratch2, name, miss);
326
327 if (lookup->IsProperty() && lookup->IsCacheable()) {
328 compiler->CompileCacheable(masm,
329 stub_compiler,
330 receiver,
331 reg,
332 scratch1,
333 scratch2,
334 holder,
335 lookup,
336 name,
337 miss);
338 } else {
339 compiler->CompileRegular(masm,
340 receiver,
341 reg,
342 scratch2,
343 holder,
344 miss);
345 }
346 }
347
348
349 class LoadInterceptorCompiler BASE_EMBEDDED {
350 public:
351 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
352
353 void CompileCacheable(MacroAssembler* masm,
354 StubCompiler* stub_compiler,
355 Register receiver,
356 Register holder,
357 Register scratch1,
358 Register scratch2,
359 JSObject* interceptor_holder,
360 LookupResult* lookup,
361 String* name,
362 Label* miss_label) {
363 AccessorInfo* callback = NULL;
364 bool optimize = false;
365 // So far the most popular follow ups for interceptor loads are FIELD
366 // and CALLBACKS, so inline only them, other cases may be added
367 // later.
368 if (lookup->type() == FIELD) {
369 optimize = true;
370 } else if (lookup->type() == CALLBACKS) {
371 Object* callback_object = lookup->GetCallbackObject();
372 if (callback_object->IsAccessorInfo()) {
373 callback = AccessorInfo::cast(callback_object);
374 optimize = callback->getter() != NULL;
375 }
376 }
377
378 if (!optimize) {
379 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
380 miss_label);
381 return;
382 }
383
384 // Save necessary data before invoking an interceptor.
385 // Requires a frame to make GC aware of pushed pointers.
386 __ EnterInternalFrame();
387
388 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
389 // CALLBACKS case needs a receiver to be passed into C++ callback.
390 __ push(receiver);
391 }
392 __ push(holder);
393 __ push(name_);
394
395 // Invoke an interceptor. Note: map checks from receiver to
396 // interceptor's holder has been compiled before (see a caller
397 // of this method.)
398 CompileCallLoadPropertyWithInterceptor(masm,
399 receiver,
400 holder,
401 name_,
402 interceptor_holder);
403
404 // Check if interceptor provided a value for property. If it's
405 // the case, return immediately.
406 Label interceptor_failed;
407 __ cmp(eax, Factory::no_interceptor_result_sentinel());
408 __ j(equal, &interceptor_failed);
409 __ LeaveInternalFrame();
410 __ ret(0);
411
412 __ bind(&interceptor_failed);
413 __ pop(name_);
414 __ pop(holder);
415 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
416 __ pop(receiver);
417 }
418
419 __ LeaveInternalFrame();
420
421 // Check that the maps from interceptor's holder to lookup's holder
422 // haven't changed. And load lookup's holder into |holder| register.
423 if (interceptor_holder != lookup->holder()) {
424 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
425 lookup->holder(), scratch1,
426 scratch2,
427 name,
428 miss_label);
429 }
430
431 if (lookup->type() == FIELD) {
432 // We found FIELD property in prototype chain of interceptor's holder.
433 // Retrieve a field from field's holder.
434 stub_compiler->GenerateFastPropertyLoad(masm, eax,
435 holder, lookup->holder(),
436 lookup->GetFieldIndex());
437 __ ret(0);
438 } else {
439 // We found CALLBACKS property in prototype chain of interceptor's
440 // holder.
441 ASSERT(lookup->type() == CALLBACKS);
442 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
443 ASSERT(callback != NULL);
444 ASSERT(callback->getter() != NULL);
445
446 // Tail call to runtime.
447 // Important invariant in CALLBACKS case: the code above must be
448 // structured to never clobber |receiver| register.
449 __ pop(scratch2); // return address
450 __ push(receiver);
451 __ push(holder);
452 __ mov(holder, Immediate(Handle<AccessorInfo>(callback)));
453 __ push(holder);
454 __ push(FieldOperand(holder, AccessorInfo::kDataOffset));
455 __ push(name_);
456 __ push(scratch2); // restore return address
457
458 ExternalReference ref =
459 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
460 __ TailCallExternalReference(ref, 5, 1);
461 }
462 }
463
464
465 void CompileRegular(MacroAssembler* masm,
466 Register receiver,
467 Register holder,
468 Register scratch,
469 JSObject* interceptor_holder,
470 Label* miss_label) {
471 __ pop(scratch); // save old return address
472 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
473 __ push(scratch); // restore old return address
474
475 ExternalReference ref = ExternalReference(
476 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
477 __ TailCallExternalReference(ref, 5, 1);
478 }
479
480 private:
481 Register name_;
482 };
483
484
485 // Reserves space for the extra arguments to FastHandleApiCall in the 303 // Reserves space for the extra arguments to FastHandleApiCall in the
486 // caller's frame. 304 // caller's frame.
487 // 305 //
488 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 306 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
489 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 307 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
490 // ----------- S t a t e ------------- 308 // ----------- S t a t e -------------
491 // -- esp[0] : return address 309 // -- esp[0] : return address
492 // -- esp[4] : last argument in the internal frame of the caller 310 // -- esp[4] : last argument in the internal frame of the caller
493 // ----------------------------------- 311 // -----------------------------------
494 __ pop(scratch); 312 __ pop(scratch);
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 CheckPrototypes(object, receiver, holder, 862 CheckPrototypes(object, receiver, holder,
1045 scratch1, scratch2, name, miss); 863 scratch1, scratch2, name, miss);
1046 864
1047 // Return the constant value. 865 // Return the constant value.
1048 __ mov(eax, Handle<Object>(value)); 866 __ mov(eax, Handle<Object>(value));
1049 __ ret(0); 867 __ ret(0);
1050 } 868 }
1051 869
1052 870
1053 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 871 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1054 JSObject* holder, 872 JSObject* interceptor_holder,
1055 LookupResult* lookup, 873 LookupResult* lookup,
1056 Register receiver, 874 Register receiver,
1057 Register name_reg, 875 Register name_reg,
1058 Register scratch1, 876 Register scratch1,
1059 Register scratch2, 877 Register scratch2,
1060 String* name, 878 String* name,
1061 Label* miss) { 879 Label* miss) {
1062 LoadInterceptorCompiler compiler(name_reg); 880 ASSERT(interceptor_holder->HasNamedInterceptor());
1063 CompileLoadInterceptor(&compiler, 881 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1064 this, 882
1065 masm(), 883 // Check that the receiver isn't a smi.
1066 object, 884 __ test(receiver, Immediate(kSmiTagMask));
1067 holder, 885 __ j(zero, miss, not_taken);
1068 name, 886
1069 lookup, 887 // So far the most popular follow ups for interceptor loads are FIELD
1070 receiver, 888 // and CALLBACKS, so inline only them, other cases may be added
1071 scratch1, 889 // later.
1072 scratch2, 890 bool compile_followup_inline = false;
1073 miss); 891 if (lookup->IsProperty() && lookup->IsCacheable()) {
892 if (lookup->type() == FIELD) {
893 compile_followup_inline = true;
894 } else if (lookup->type() == CALLBACKS &&
895 lookup->GetCallbackObject()->IsAccessorInfo() &&
896 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
897 compile_followup_inline = true;
898 }
899 }
900
901 if (compile_followup_inline) {
902 // Compile the interceptor call, followed by inline code to load the
903 // property from further up the prototype chain if the call fails.
904 // Check that the maps haven't changed.
905 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
906 scratch1, scratch2, name, miss);
907 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
908
909 // Save necessary data before invoking an interceptor.
910 // Requires a frame to make GC aware of pushed pointers.
911 __ EnterInternalFrame();
912
913 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
914 // CALLBACKS case needs a receiver to be passed into C++ callback.
915 __ push(receiver);
916 }
917 __ push(holder_reg);
918 __ push(name_reg);
919
920 // Invoke an interceptor. Note: map checks from receiver to
921 // interceptor's holder has been compiled before (see a caller
922 // of this method.)
923 CompileCallLoadPropertyWithInterceptor(masm(),
924 receiver,
925 holder_reg,
926 name_reg,
927 interceptor_holder);
928
929 // Check if interceptor provided a value for property. If it's
930 // the case, return immediately.
931 Label interceptor_failed;
932 __ cmp(eax, Factory::no_interceptor_result_sentinel());
933 __ j(equal, &interceptor_failed);
934 __ LeaveInternalFrame();
935 __ ret(0);
936
937 __ bind(&interceptor_failed);
938 __ pop(name_reg);
939 __ pop(holder_reg);
940 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
941 __ pop(receiver);
942 }
943
944 __ LeaveInternalFrame();
945
946 // Check that the maps from interceptor's holder to lookup's holder
947 // haven't changed. And load lookup's holder into holder_reg.
948 if (interceptor_holder != lookup->holder()) {
949 holder_reg = CheckPrototypes(interceptor_holder,
950 holder_reg,
951 lookup->holder(),
952 scratch1,
953 scratch2,
954 name,
955 miss);
956 }
antonm 2010/05/27 13:39:40 ditto for ia32 and x64
957
958 if (lookup->type() == FIELD) {
959 // We found FIELD property in prototype chain of interceptor's holder.
960 // Retrieve a field from field's holder.
961 GenerateFastPropertyLoad(masm(), eax, holder_reg,
962 lookup->holder(), lookup->GetFieldIndex());
963 __ ret(0);
964 } else {
965 // We found CALLBACKS property in prototype chain of interceptor's
966 // holder.
967 ASSERT(lookup->type() == CALLBACKS);
968 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
969 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
970 ASSERT(callback != NULL);
971 ASSERT(callback->getter() != NULL);
972
973 // Tail call to runtime.
974 // Important invariant in CALLBACKS case: the code above must be
975 // structured to never clobber |receiver| register.
976 __ pop(scratch2); // return address
977 __ push(receiver);
978 __ push(holder_reg);
979 __ mov(holder_reg, Immediate(Handle<AccessorInfo>(callback)));
980 __ push(holder_reg);
981 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
982 __ push(name_reg);
983 __ push(scratch2); // restore return address
984
985 ExternalReference ref =
986 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
987 __ TailCallExternalReference(ref, 5, 1);
988 }
989 } else { // !compile_followup_inline
990 // Call the runtime system to load the interceptor.
991 // Check that the maps haven't changed.
992 Register holder_reg =
993 CheckPrototypes(object, receiver, interceptor_holder,
994 scratch1, scratch2, name, miss);
995 __ pop(scratch2); // save old return address
996 PushInterceptorArguments(masm(), receiver, holder_reg,
997 name_reg, interceptor_holder);
998 __ push(scratch2); // restore old return address
999
1000 ExternalReference ref = ExternalReference(
1001 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
1002 __ TailCallExternalReference(ref, 5, 1);
1003 }
1074 } 1004 }
1075 1005
1076 1006
1077 // TODO(1241006): Avoid having lazy compile stubs specialized by the 1007 // TODO(1241006): Avoid having lazy compile stubs specialized by the
1078 // number of arguments. It is not needed anymore. 1008 // number of arguments. It is not needed anymore.
1079 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) { 1009 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
1080 // Enter an internal frame. 1010 // Enter an internal frame.
1081 __ EnterInternalFrame(); 1011 __ EnterInternalFrame();
1082 1012
1083 // Push a copy of the function onto the stack. 1013 // Push a copy of the function onto the stack.
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after
2542 // Return the generated code. 2472 // Return the generated code.
2543 return GetCode(); 2473 return GetCode();
2544 } 2474 }
2545 2475
2546 2476
2547 #undef __ 2477 #undef __
2548 2478
2549 } } // namespace v8::internal 2479 } } // namespace v8::internal
2550 2480
2551 #endif // V8_TARGET_ARCH_IA32 2481 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698