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

Side by Side Diff: src/x64/stub-cache-x64.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, 6 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
« src/ia32/stub-cache-ia32.cc ('K') | « src/ia32/stub-cache-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 Register receiver, 368 Register receiver,
369 Register result, 369 Register result,
370 Register scratch, 370 Register scratch,
371 Label* miss_label) { 371 Label* miss_label) {
372 __ TryGetFunctionPrototype(receiver, result, miss_label); 372 __ TryGetFunctionPrototype(receiver, result, miss_label);
373 if (!result.is(rax)) __ movq(rax, result); 373 if (!result.is(rax)) __ movq(rax, result);
374 __ ret(0); 374 __ ret(0);
375 } 375 }
376 376
377 377
378 template <class Compiler>
379 static void CompileLoadInterceptor(Compiler* compiler,
380 StubCompiler* stub_compiler,
381 MacroAssembler* masm,
382 JSObject* object,
383 JSObject* holder,
384 String* name,
385 LookupResult* lookup,
386 Register receiver,
387 Register scratch1,
388 Register scratch2,
389 Label* miss) {
390 ASSERT(holder->HasNamedInterceptor());
391 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
392
393 // Check that the receiver isn't a smi.
394 __ JumpIfSmi(receiver, miss);
395
396 // Check that the maps haven't changed.
397 Register reg =
398 stub_compiler->CheckPrototypes(object, receiver, holder,
399 scratch1, scratch2, name, miss);
400
401 if (lookup->IsProperty() && lookup->IsCacheable()) {
402 compiler->CompileCacheable(masm,
403 stub_compiler,
404 receiver,
405 reg,
406 scratch1,
407 scratch2,
408 holder,
409 lookup,
410 name,
411 miss);
412 } else {
413 compiler->CompileRegular(masm,
414 receiver,
415 reg,
416 scratch2,
417 holder,
418 miss);
419 }
420 }
421
422
423 class LoadInterceptorCompiler BASE_EMBEDDED {
424 public:
425 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
426
427 void CompileCacheable(MacroAssembler* masm,
428 StubCompiler* stub_compiler,
429 Register receiver,
430 Register holder,
431 Register scratch1,
432 Register scratch2,
433 JSObject* interceptor_holder,
434 LookupResult* lookup,
435 String* name,
436 Label* miss_label) {
437 AccessorInfo* callback = NULL;
438 bool optimize = false;
439 // So far the most popular follow ups for interceptor loads are FIELD
440 // and CALLBACKS, so inline only them, other cases may be added
441 // later.
442 if (lookup->type() == FIELD) {
443 optimize = true;
444 } else if (lookup->type() == CALLBACKS) {
445 Object* callback_object = lookup->GetCallbackObject();
446 if (callback_object->IsAccessorInfo()) {
447 callback = AccessorInfo::cast(callback_object);
448 optimize = callback->getter() != NULL;
449 }
450 }
451
452 if (!optimize) {
453 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
454 miss_label);
455 return;
456 }
457
458 // Save necessary data before invoking an interceptor.
459 // Requires a frame to make GC aware of pushed pointers.
460 __ EnterInternalFrame();
461
462 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
463 // CALLBACKS case needs a receiver to be passed into C++ callback.
464 __ push(receiver);
465 }
466 __ push(holder);
467 __ push(name_);
468
469 // Invoke an interceptor. Note: map checks from receiver to
470 // interceptor's holder has been compiled before (see a caller
471 // of this method.)
472 CompileCallLoadPropertyWithInterceptor(masm,
473 receiver,
474 holder,
475 name_,
476 interceptor_holder);
477
478 // Check if interceptor provided a value for property. If it's
479 // the case, return immediately.
480 Label interceptor_failed;
481 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
482 __ j(equal, &interceptor_failed);
483 __ LeaveInternalFrame();
484 __ ret(0);
485
486 __ bind(&interceptor_failed);
487 __ pop(name_);
488 __ pop(holder);
489 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
490 __ pop(receiver);
491 }
492
493 __ LeaveInternalFrame();
494
495 // Check that the maps from interceptor's holder to lookup's holder
496 // haven't changed. And load lookup's holder into |holder| register.
497 if (interceptor_holder != lookup->holder()) {
498 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
499 lookup->holder(), scratch1,
500 scratch2,
501 name,
502 miss_label);
503 }
504
505 if (lookup->type() == FIELD) {
506 // We found FIELD property in prototype chain of interceptor's holder.
507 // Retrieve a field from field's holder.
508 stub_compiler->GenerateFastPropertyLoad(masm,
509 rax,
510 holder,
511 lookup->holder(),
512 lookup->GetFieldIndex());
513 __ ret(0);
514 } else {
515 // We found CALLBACKS property in prototype chain of interceptor's
516 // holder.
517 ASSERT(lookup->type() == CALLBACKS);
518 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
519 ASSERT(callback != NULL);
520 ASSERT(callback->getter() != NULL);
521
522 // Tail call to runtime.
523 // Important invariant in CALLBACKS case: the code above must be
524 // structured to never clobber |receiver| register.
525 __ pop(scratch2); // return address
526 __ push(receiver);
527 __ push(holder);
528 __ Move(holder, Handle<AccessorInfo>(callback));
529 __ push(holder);
530 __ push(FieldOperand(holder, AccessorInfo::kDataOffset));
531 __ push(name_);
532 __ push(scratch2); // restore return address
533
534 ExternalReference ref =
535 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
536 __ TailCallExternalReference(ref, 5, 1);
537 }
538 }
539
540
541 void CompileRegular(MacroAssembler* masm,
542 Register receiver,
543 Register holder,
544 Register scratch,
545 JSObject* interceptor_holder,
546 Label* miss_label) {
547 __ pop(scratch); // save old return address
548 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
549 __ push(scratch); // restore old return address
550
551 ExternalReference ref = ExternalReference(
552 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
553 __ TailCallExternalReference(ref, 5, 1);
554 }
555
556 private:
557 Register name_;
558 };
559
560
561 // Reserves space for the extra arguments to FastHandleApiCall in the 378 // Reserves space for the extra arguments to FastHandleApiCall in the
562 // caller's frame. 379 // caller's frame.
563 // 380 //
564 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 381 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
565 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 382 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
566 // ----------- S t a t e ------------- 383 // ----------- S t a t e -------------
567 // -- rsp[0] : return address 384 // -- rsp[0] : return address
568 // -- rsp[8] : last argument in the internal frame of the caller 385 // -- rsp[8] : last argument in the internal frame of the caller
569 // ----------------------------------- 386 // -----------------------------------
570 __ movq(scratch, Operand(rsp, 0)); 387 __ movq(scratch, Operand(rsp, 0));
(...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after
2118 __ LeaveInternalFrame(); 1935 __ LeaveInternalFrame();
2119 1936
2120 // Do a tail-call of the compiled function. 1937 // Do a tail-call of the compiled function.
2121 __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); 1938 __ lea(rcx, FieldOperand(rax, Code::kHeaderSize));
2122 __ jmp(rcx); 1939 __ jmp(rcx);
2123 1940
2124 return GetCodeWithFlags(flags, "LazyCompileStub"); 1941 return GetCodeWithFlags(flags, "LazyCompileStub");
2125 } 1942 }
2126 1943
2127 1944
2128
2129 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 1945 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
2130 JSObject* holder, 1946 JSObject* interceptor_holder,
2131 LookupResult* lookup, 1947 LookupResult* lookup,
2132 Register receiver, 1948 Register receiver,
2133 Register name_reg, 1949 Register name_reg,
2134 Register scratch1, 1950 Register scratch1,
2135 Register scratch2, 1951 Register scratch2,
2136 String* name, 1952 String* name,
2137 Label* miss) { 1953 Label* miss) {
2138 LoadInterceptorCompiler compiler(name_reg); 1954 ASSERT(interceptor_holder->HasNamedInterceptor());
2139 CompileLoadInterceptor(&compiler, 1955 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
2140 this, 1956
2141 masm(), 1957 // Check that the receiver isn't a smi.
2142 object, 1958 __ JumpIfSmi(receiver, miss);
2143 holder, 1959
2144 name, 1960 // So far the most popular follow ups for interceptor loads are FIELD
2145 lookup, 1961 // and CALLBACKS, so inline only them, other cases may be added
2146 receiver, 1962 // later.
2147 scratch1, 1963 bool compile_followup_inline = false;
2148 scratch2, 1964 if (lookup->IsProperty() && lookup->IsCacheable()) {
2149 miss); 1965 if (lookup->type() == FIELD) {
1966 compile_followup_inline = true;
1967 } else if (lookup->type() == CALLBACKS &&
1968 lookup->GetCallbackObject()->IsAccessorInfo() &&
1969 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
1970 compile_followup_inline = true;
1971 }
1972 }
1973
1974 if (compile_followup_inline) {
1975 // Compile the interceptor call, followed by inline code to load the
1976 // property from further up the prototype chain if the call fails.
1977 // Check that the maps haven't changed.
1978 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1979 scratch1, scratch2, name, miss);
1980 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1981
1982 // Save necessary data before invoking an interceptor.
1983 // Requires a frame to make GC aware of pushed pointers.
1984 __ EnterInternalFrame();
1985
1986 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1987 // CALLBACKS case needs a receiver to be passed into C++ callback.
1988 __ push(receiver);
1989 }
1990 __ push(holder_reg);
1991 __ push(name_reg);
1992
1993 // Invoke an interceptor. Note: map checks from receiver to
1994 // interceptor's holder has been compiled before (see a caller
1995 // of this method.)
1996 CompileCallLoadPropertyWithInterceptor(masm(),
1997 receiver,
1998 holder_reg,
1999 name_reg,
2000 interceptor_holder);
2001
2002 // Check if interceptor provided a value for property. If it's
2003 // the case, return immediately.
2004 Label interceptor_failed;
2005 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
2006 __ j(equal, &interceptor_failed);
2007 __ LeaveInternalFrame();
2008 __ ret(0);
2009
2010 __ bind(&interceptor_failed);
2011 __ pop(name_reg);
2012 __ pop(holder_reg);
2013 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
2014 __ pop(receiver);
2015 }
2016
2017 __ LeaveInternalFrame();
2018
2019 // Check that the maps from interceptor's holder to lookup's holder
2020 // haven't changed. And load lookup's holder into |holder| register.
2021 if (interceptor_holder != lookup->holder()) {
2022 holder_reg = CheckPrototypes(interceptor_holder,
2023 holder_reg,
2024 lookup->holder(),
2025 scratch1,
2026 scratch2,
2027 name,
2028 miss);
2029 }
2030
2031 if (lookup->type() == FIELD) {
2032 // We found FIELD property in prototype chain of interceptor's holder.
2033 // Retrieve a field from field's holder.
2034 GenerateFastPropertyLoad(masm(), rax, holder_reg,
2035 lookup->holder(), lookup->GetFieldIndex());
2036 __ ret(0);
2037 } else {
2038 // We found CALLBACKS property in prototype chain of interceptor's
2039 // holder.
2040 ASSERT(lookup->type() == CALLBACKS);
2041 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
2042 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
2043 ASSERT(callback != NULL);
2044 ASSERT(callback->getter() != NULL);
2045
2046 // Tail call to runtime.
2047 // Important invariant in CALLBACKS case: the code above must be
2048 // structured to never clobber |receiver| register.
2049 __ pop(scratch2); // return address
2050 __ push(receiver);
2051 __ push(holder_reg);
2052 __ Move(holder_reg, Handle<AccessorInfo>(callback));
2053 __ push(holder_reg);
2054 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
2055 __ push(name_reg);
2056 __ push(scratch2); // restore return address
2057
2058 ExternalReference ref =
2059 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
2060 __ TailCallExternalReference(ref, 5, 1);
2061 }
2062 } else { // !compile_followup_inline
2063 // Call the runtime system to load the interceptor.
2064 // Check that the maps haven't changed.
2065 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
2066 scratch1, scratch2, name, miss);
2067 __ pop(scratch2); // save old return address
2068 PushInterceptorArguments(masm(), receiver, holder_reg,
2069 name_reg, interceptor_holder);
2070 __ push(scratch2); // restore old return address
2071
2072 ExternalReference ref = ExternalReference(
2073 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
2074 __ TailCallExternalReference(ref, 5, 1);
2075 }
2150 } 2076 }
2151 2077
2152 2078
2153 bool StubCompiler::GenerateLoadCallback(JSObject* object, 2079 bool StubCompiler::GenerateLoadCallback(JSObject* object,
2154 JSObject* holder, 2080 JSObject* holder,
2155 Register receiver, 2081 Register receiver,
2156 Register name_reg, 2082 Register name_reg,
2157 Register scratch1, 2083 Register scratch1,
2158 Register scratch2, 2084 Register scratch2,
2159 AccessorInfo* callback, 2085 AccessorInfo* callback,
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2400 // Return the generated code. 2326 // Return the generated code.
2401 return GetCode(); 2327 return GetCode();
2402 } 2328 }
2403 2329
2404 2330
2405 #undef __ 2331 #undef __
2406 2332
2407 } } // namespace v8::internal 2333 } } // namespace v8::internal
2408 2334
2409 #endif // V8_TARGET_ARCH_X64 2335 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/ia32/stub-cache-ia32.cc ('K') | « src/ia32/stub-cache-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698