Revision f230a1cf deps/v8/src/ia32/stub-cache-ia32.cc
deps/v8/src/ia32/stub-cache-ia32.cc | ||
---|---|---|
329 | 329 |
Register receiver, |
330 | 330 |
Register scratch1, |
331 | 331 |
Register scratch2, |
332 |
Label* miss, |
|
333 |
bool support_wrappers) { |
|
332 |
Label* miss) { |
|
334 | 333 |
Label check_wrapper; |
335 | 334 |
|
336 | 335 |
// Check if the object is a string leaving the instance type in the |
337 | 336 |
// scratch register. |
338 |
GenerateStringCheck(masm, receiver, scratch1, miss, |
|
339 |
support_wrappers ? &check_wrapper : miss); |
|
337 |
GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); |
|
340 | 338 |
|
341 | 339 |
// Load length from the string and convert to a smi. |
342 | 340 |
__ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
343 | 341 |
__ ret(0); |
344 | 342 |
|
345 |
if (support_wrappers) { |
|
346 |
// Check if the object is a JSValue wrapper. |
|
347 |
__ bind(&check_wrapper); |
|
348 |
__ cmp(scratch1, JS_VALUE_TYPE); |
|
349 |
__ j(not_equal, miss); |
|
343 |
// Check if the object is a JSValue wrapper. |
|
344 |
__ bind(&check_wrapper); |
|
345 |
__ cmp(scratch1, JS_VALUE_TYPE); |
|
346 |
__ j(not_equal, miss); |
|
350 | 347 |
|
351 |
// Check if the wrapped value is a string and load the length |
|
352 |
// directly if it is. |
|
353 |
__ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
|
354 |
GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
|
355 |
__ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
|
356 |
__ ret(0); |
|
357 |
} |
|
348 |
// Check if the wrapped value is a string and load the length |
|
349 |
// directly if it is. |
|
350 |
__ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
|
351 |
GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
|
352 |
__ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
|
353 |
__ ret(0); |
|
358 | 354 |
} |
359 | 355 |
|
360 | 356 |
|
... | ... | |
462 | 458 |
// Generates call to API function. |
463 | 459 |
static void GenerateFastApiCall(MacroAssembler* masm, |
464 | 460 |
const CallOptimization& optimization, |
465 |
int argc) { |
|
461 |
int argc, |
|
462 |
bool restore_context) { |
|
466 | 463 |
// ----------- S t a t e ------------- |
467 | 464 |
// -- esp[0] : return address |
468 |
// -- esp[4] : object passing the type check |
|
469 |
// (last fast api call extra argument, |
|
470 |
// set by CheckPrototypes) |
|
471 |
// -- esp[8] : api function |
|
472 |
// (first fast api call extra argument) |
|
473 |
// -- esp[12] : api call data |
|
474 |
// -- esp[16] : isolate |
|
475 |
// -- esp[20] : ReturnValue default value |
|
476 |
// -- esp[24] : ReturnValue |
|
477 |
// -- esp[28] : last argument |
|
465 |
// -- esp[4] - esp[28] : FunctionCallbackInfo, incl. |
|
466 |
// : object passing the type check |
|
467 |
// (set by CheckPrototypes) |
|
468 |
// -- esp[32] : last argument |
|
478 | 469 |
// -- ... |
479 |
// -- esp[(argc + 6) * 4] : first argument
|
|
480 |
// -- esp[(argc + 7) * 4] : receiver
|
|
470 |
// -- esp[(argc + 7) * 4] : first argument
|
|
471 |
// -- esp[(argc + 8) * 4] : receiver
|
|
481 | 472 |
// ----------------------------------- |
473 |
|
|
474 |
typedef FunctionCallbackArguments FCA; |
|
475 |
// Save calling context. |
|
476 |
__ mov(Operand(esp, (1 + FCA::kContextSaveIndex) * kPointerSize), esi); |
|
477 |
|
|
482 | 478 |
// Get the function and setup the context. |
483 | 479 |
Handle<JSFunction> function = optimization.constant_function(); |
484 | 480 |
__ LoadHeapObject(edi, function); |
485 | 481 |
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
486 | 482 |
|
487 |
// Pass the additional arguments.
|
|
488 |
__ mov(Operand(esp, 2 * kPointerSize), edi);
|
|
483 |
// Construct the FunctionCallbackInfo.
|
|
484 |
__ mov(Operand(esp, (1 + FCA::kCalleeIndex) * kPointerSize), edi);
|
|
489 | 485 |
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
490 | 486 |
Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
491 | 487 |
if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
492 | 488 |
__ mov(ecx, api_call_info); |
493 | 489 |
__ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
494 |
__ mov(Operand(esp, 3 * kPointerSize), ebx);
|
|
490 |
__ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), ebx);
|
|
495 | 491 |
} else { |
496 |
__ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); |
|
492 |
__ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), |
|
493 |
Immediate(call_data)); |
|
497 | 494 |
} |
498 |
__ mov(Operand(esp, 4 * kPointerSize),
|
|
495 |
__ mov(Operand(esp, (1 + FCA::kIsolateIndex) * kPointerSize),
|
|
499 | 496 |
Immediate(reinterpret_cast<int>(masm->isolate()))); |
500 |
__ mov(Operand(esp, 5 * kPointerSize),
|
|
497 |
__ mov(Operand(esp, (1 + FCA::kReturnValueOffset) * kPointerSize),
|
|
501 | 498 |
masm->isolate()->factory()->undefined_value()); |
502 |
__ mov(Operand(esp, 6 * kPointerSize),
|
|
499 |
__ mov(Operand(esp, (1 + FCA::kReturnValueDefaultValueIndex) * kPointerSize),
|
|
503 | 500 |
masm->isolate()->factory()->undefined_value()); |
504 | 501 |
|
505 | 502 |
// Prepare arguments. |
506 |
STATIC_ASSERT(kFastApiCallArguments == 6); |
|
507 |
__ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
|
508 |
|
|
503 |
STATIC_ASSERT(kFastApiCallArguments == 7); |
|
504 |
__ lea(eax, Operand(esp, 1 * kPointerSize)); |
|
509 | 505 |
|
510 | 506 |
// API function gets reference to the v8::Arguments. If CPU profiler |
511 | 507 |
// is enabled wrapper function will be called and we need to pass |
... | ... | |
521 | 517 |
Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
522 | 518 |
__ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
523 | 519 |
|
524 |
// v8::Arguments::implicit_args_.
|
|
520 |
// FunctionCallbackInfo::implicit_args_.
|
|
525 | 521 |
__ mov(ApiParameterOperand(2), eax); |
526 |
__ add(eax, Immediate(argc * kPointerSize));
|
|
527 |
// v8::Arguments::values_.
|
|
522 |
__ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
|
|
523 |
// FunctionCallbackInfo::values_.
|
|
528 | 524 |
__ mov(ApiParameterOperand(3), eax); |
529 |
// v8::Arguments::length_.
|
|
525 |
// FunctionCallbackInfo::length_.
|
|
530 | 526 |
__ Set(ApiParameterOperand(4), Immediate(argc)); |
531 |
// v8::Arguments::is_construct_call_.
|
|
527 |
// FunctionCallbackInfo::is_construct_call_.
|
|
532 | 528 |
__ Set(ApiParameterOperand(5), Immediate(0)); |
533 | 529 |
|
534 | 530 |
// v8::InvocationCallback's argument. |
... | ... | |
537 | 533 |
|
538 | 534 |
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
539 | 535 |
|
536 |
Operand context_restore_operand(ebp, |
|
537 |
(2 + FCA::kContextSaveIndex) * kPointerSize); |
|
538 |
Operand return_value_operand(ebp, |
|
539 |
(2 + FCA::kReturnValueOffset) * kPointerSize); |
|
540 | 540 |
__ CallApiFunctionAndReturn(function_address, |
541 | 541 |
thunk_address, |
542 | 542 |
ApiParameterOperand(1), |
543 | 543 |
argc + kFastApiCallArguments + 1, |
544 |
kFastApiCallArguments + 1); |
|
544 |
return_value_operand, |
|
545 |
restore_context ? |
|
546 |
&context_restore_operand : NULL); |
|
545 | 547 |
} |
546 | 548 |
|
547 | 549 |
|
... | ... | |
556 | 558 |
ASSERT(!receiver.is(scratch)); |
557 | 559 |
|
558 | 560 |
const int stack_space = kFastApiCallArguments + argc + 1; |
561 |
const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; |
|
559 | 562 |
// Copy return value. |
560 | 563 |
__ mov(scratch, Operand(esp, 0)); |
561 | 564 |
// Assign stack space for the call arguments. |
... | ... | |
563 | 566 |
// Move the return address on top of the stack. |
564 | 567 |
__ mov(Operand(esp, 0), scratch); |
565 | 568 |
// Write holder to stack frame. |
566 |
__ mov(Operand(esp, 1 * kPointerSize), receiver);
|
|
569 |
__ mov(Operand(esp, kHolderIndex * kPointerSize), receiver);
|
|
567 | 570 |
// Write receiver to stack frame. |
568 | 571 |
int index = stack_space; |
569 | 572 |
__ mov(Operand(esp, index-- * kPointerSize), receiver); |
... | ... | |
574 | 577 |
__ mov(Operand(esp, index-- * kPointerSize), values[i]); |
575 | 578 |
} |
576 | 579 |
|
577 |
GenerateFastApiCall(masm, optimization, argc); |
|
580 |
GenerateFastApiCall(masm, optimization, argc, true);
|
|
578 | 581 |
} |
579 | 582 |
|
580 | 583 |
|
... | ... | |
688 | 691 |
|
689 | 692 |
// Invoke function. |
690 | 693 |
if (can_do_fast_api_call) { |
691 |
GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
|
694 |
GenerateFastApiCall(masm, optimization, arguments_.immediate(), false);
|
|
692 | 695 |
} else { |
693 | 696 |
CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
694 | 697 |
? CALL_AS_FUNCTION |
... | ... | |
776 | 779 |
}; |
777 | 780 |
|
778 | 781 |
|
779 |
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
|
|
780 |
Label* label,
|
|
781 |
Handle<Name> name) {
|
|
782 |
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
|
783 |
Label* label, |
|
784 |
Handle<Name> name) { |
|
782 | 785 |
if (!label->is_unused()) { |
783 | 786 |
__ bind(label); |
784 | 787 |
__ mov(this->name(), Immediate(name)); |
... | ... | |
809 | 812 |
} |
810 | 813 |
|
811 | 814 |
|
812 |
void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
|
|
815 |
void StoreStubCompiler::GenerateNegativeHolderLookup( |
|
813 | 816 |
MacroAssembler* masm, |
814 | 817 |
Handle<JSObject> holder, |
815 | 818 |
Register holder_reg, |
... | ... | |
827 | 830 |
|
828 | 831 |
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
829 | 832 |
// store is successful. |
830 |
void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
|
|
831 |
Handle<JSObject> object,
|
|
832 |
LookupResult* lookup,
|
|
833 |
Handle<Map> transition,
|
|
834 |
Handle<Name> name,
|
|
835 |
Register receiver_reg,
|
|
836 |
Register storage_reg,
|
|
837 |
Register value_reg,
|
|
838 |
Register scratch1,
|
|
839 |
Register scratch2,
|
|
840 |
Register unused,
|
|
841 |
Label* miss_label,
|
|
842 |
Label* slow) {
|
|
833 |
void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
|
834 |
Handle<JSObject> object, |
|
835 |
LookupResult* lookup, |
|
836 |
Handle<Map> transition, |
|
837 |
Handle<Name> name, |
|
838 |
Register receiver_reg, |
|
839 |
Register storage_reg, |
|
840 |
Register value_reg, |
|
841 |
Register scratch1, |
|
842 |
Register scratch2, |
|
843 |
Register unused, |
|
844 |
Label* miss_label, |
|
845 |
Label* slow) { |
|
843 | 846 |
int descriptor = transition->LastAdded(); |
844 | 847 |
DescriptorArray* descriptors = transition->instance_descriptors(); |
845 | 848 |
PropertyDetails details = descriptors->GetDetails(descriptor); |
... | ... | |
862 | 865 |
__ SmiUntag(value_reg); |
863 | 866 |
if (CpuFeatures::IsSupported(SSE2)) { |
864 | 867 |
CpuFeatureScope use_sse2(masm, SSE2); |
865 |
__ cvtsi2sd(xmm0, value_reg);
|
|
868 |
__ Cvtsi2sd(xmm0, value_reg);
|
|
866 | 869 |
} else { |
867 | 870 |
__ push(value_reg); |
868 | 871 |
__ fild_s(Operand(esp, 0)); |
... | ... | |
876 | 879 |
miss_label, DONT_DO_SMI_CHECK); |
877 | 880 |
if (CpuFeatures::IsSupported(SSE2)) { |
878 | 881 |
CpuFeatureScope use_sse2(masm, SSE2); |
879 |
__ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
|
|
882 |
__ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
|
|
880 | 883 |
} else { |
881 | 884 |
__ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
882 | 885 |
} |
... | ... | |
884 | 887 |
__ bind(&do_store); |
885 | 888 |
if (CpuFeatures::IsSupported(SSE2)) { |
886 | 889 |
CpuFeatureScope use_sse2(masm, SSE2); |
887 |
__ movdbl(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
|
|
890 |
__ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
|
|
888 | 891 |
} else { |
889 | 892 |
__ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); |
890 | 893 |
} |
... | ... | |
998 | 1001 |
|
999 | 1002 |
// Both name_reg and receiver_reg are preserved on jumps to miss_label, |
1000 | 1003 |
// but may be destroyed if store is successful. |
1001 |
void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
|
|
1002 |
Handle<JSObject> object,
|
|
1003 |
LookupResult* lookup,
|
|
1004 |
Register receiver_reg,
|
|
1005 |
Register name_reg,
|
|
1006 |
Register value_reg,
|
|
1007 |
Register scratch1,
|
|
1008 |
Register scratch2,
|
|
1009 |
Label* miss_label) {
|
|
1004 |
void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
|
1005 |
Handle<JSObject> object, |
|
1006 |
LookupResult* lookup, |
|
1007 |
Register receiver_reg, |
|
1008 |
Register name_reg, |
|
1009 |
Register value_reg, |
|
1010 |
Register scratch1, |
|
1011 |
Register scratch2, |
|
1012 |
Label* miss_label) { |
|
1010 | 1013 |
// Stub never generated for non-global objects that require access |
1011 | 1014 |
// checks. |
1012 | 1015 |
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
... | ... | |
1041 | 1044 |
__ SmiUntag(value_reg); |
1042 | 1045 |
if (CpuFeatures::IsSupported(SSE2)) { |
1043 | 1046 |
CpuFeatureScope use_sse2(masm, SSE2); |
1044 |
__ cvtsi2sd(xmm0, value_reg);
|
|
1047 |
__ Cvtsi2sd(xmm0, value_reg);
|
|
1045 | 1048 |
} else { |
1046 | 1049 |
__ push(value_reg); |
1047 | 1050 |
__ fild_s(Operand(esp, 0)); |
... | ... | |
1054 | 1057 |
miss_label, DONT_DO_SMI_CHECK); |
1055 | 1058 |
if (CpuFeatures::IsSupported(SSE2)) { |
1056 | 1059 |
CpuFeatureScope use_sse2(masm, SSE2); |
1057 |
__ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
|
|
1060 |
__ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
|
|
1058 | 1061 |
} else { |
1059 | 1062 |
__ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
1060 | 1063 |
} |
1061 | 1064 |
__ bind(&do_store); |
1062 | 1065 |
if (CpuFeatures::IsSupported(SSE2)) { |
1063 | 1066 |
CpuFeatureScope use_sse2(masm, SSE2); |
1064 |
__ movdbl(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
|
|
1067 |
__ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
|
|
1065 | 1068 |
} else { |
1066 | 1069 |
__ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); |
1067 | 1070 |
} |
... | ... | |
1160 | 1163 |
int save_at_depth, |
1161 | 1164 |
Label* miss, |
1162 | 1165 |
PrototypeCheckType check) { |
1166 |
const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; |
|
1163 | 1167 |
// Make sure that the type feedback oracle harvests the receiver map. |
1164 | 1168 |
// TODO(svenpanne) Remove this hack when all ICs are reworked. |
1165 | 1169 |
__ mov(scratch1, Handle<Map>(object->map())); |
... | ... | |
1176 | 1180 |
int depth = 0; |
1177 | 1181 |
|
1178 | 1182 |
if (save_at_depth == depth) { |
1179 |
__ mov(Operand(esp, kPointerSize), reg); |
|
1183 |
__ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
|
|
1180 | 1184 |
} |
1181 | 1185 |
|
1182 | 1186 |
// Traverse the prototype chain and check the maps in the prototype chain for |
... | ... | |
1237 | 1241 |
} |
1238 | 1242 |
|
1239 | 1243 |
if (save_at_depth == depth) { |
1240 |
__ mov(Operand(esp, kPointerSize), reg); |
|
1244 |
__ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
|
|
1241 | 1245 |
} |
1242 | 1246 |
|
1243 | 1247 |
// Go to the next object in the prototype chain. |
... | ... | |
1269 | 1273 |
} |
1270 | 1274 |
|
1271 | 1275 |
|
1272 |
void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
|
|
1273 |
Label* success,
|
|
1274 |
Label* miss) {
|
|
1276 |
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
|
1277 |
Label* success, |
|
1278 |
Label* miss) { |
|
1275 | 1279 |
if (!miss->is_unused()) { |
1276 | 1280 |
__ jmp(success); |
1277 | 1281 |
__ bind(miss); |
... | ... | |
1280 | 1284 |
} |
1281 | 1285 |
|
1282 | 1286 |
|
1283 |
void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
|
|
1284 |
Label* success,
|
|
1285 |
Label* miss) {
|
|
1287 |
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
|
1288 |
Label* success, |
|
1289 |
Label* miss) { |
|
1286 | 1290 |
if (!miss->is_unused()) { |
1287 | 1291 |
__ jmp(success); |
1288 | 1292 |
GenerateRestoreName(masm(), miss, name); |
... | ... | |
1291 | 1295 |
} |
1292 | 1296 |
|
1293 | 1297 |
|
1294 |
Register BaseLoadStubCompiler::CallbackHandlerFrontend(
|
|
1298 |
Register LoadStubCompiler::CallbackHandlerFrontend( |
|
1295 | 1299 |
Handle<JSObject> object, |
1296 | 1300 |
Register object_reg, |
1297 | 1301 |
Handle<JSObject> holder, |
... | ... | |
1351 | 1355 |
} |
1352 | 1356 |
|
1353 | 1357 |
|
1354 |
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
|
|
1358 |
void LoadStubCompiler::NonexistentHandlerFrontend( |
|
1355 | 1359 |
Handle<JSObject> object, |
1356 | 1360 |
Handle<JSObject> last, |
1357 | 1361 |
Handle<Name> name, |
... | ... | |
1371 | 1375 |
} |
1372 | 1376 |
|
1373 | 1377 |
|
1374 |
void BaseLoadStubCompiler::GenerateLoadField(Register reg,
|
|
1375 |
Handle<JSObject> holder,
|
|
1376 |
PropertyIndex field,
|
|
1377 |
Representation representation) {
|
|
1378 |
void LoadStubCompiler::GenerateLoadField(Register reg, |
|
1379 |
Handle<JSObject> holder, |
|
1380 |
PropertyIndex field, |
|
1381 |
Representation representation) { |
|
1378 | 1382 |
if (!reg.is(receiver())) __ mov(receiver(), reg); |
1379 | 1383 |
if (kind() == Code::LOAD_IC) { |
1380 | 1384 |
LoadFieldStub stub(field.is_inobject(holder), |
... | ... | |
1390 | 1394 |
} |
1391 | 1395 |
|
1392 | 1396 |
|
1393 |
void BaseLoadStubCompiler::GenerateLoadCallback(
|
|
1397 |
void LoadStubCompiler::GenerateLoadCallback( |
|
1394 | 1398 |
const CallOptimization& call_optimization) { |
1395 | 1399 |
GenerateFastApiCall( |
1396 | 1400 |
masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
1397 | 1401 |
} |
1398 | 1402 |
|
1399 | 1403 |
|
1400 |
void BaseLoadStubCompiler::GenerateLoadCallback(
|
|
1404 |
void LoadStubCompiler::GenerateLoadCallback( |
|
1401 | 1405 |
Register reg, |
1402 | 1406 |
Handle<ExecutableAccessorInfo> callback) { |
1403 | 1407 |
// Insert additional parameters into the stack frame above return address. |
1404 | 1408 |
ASSERT(!scratch3().is(reg)); |
1405 | 1409 |
__ pop(scratch3()); // Get return address to place it below. |
1406 | 1410 |
|
1407 |
STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 0);
|
|
1408 |
STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == -1);
|
|
1409 |
STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == -2);
|
|
1410 |
STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == -3);
|
|
1411 |
STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == -4);
|
|
1412 |
STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == -5);
|
|
1411 |
STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
|
|
1412 |
STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
|
|
1413 |
STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
|
|
1414 |
STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
|
|
1415 |
STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
|
|
1416 |
STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
|
|
1413 | 1417 |
__ push(receiver()); // receiver |
1414 |
__ mov(scratch2(), esp); |
|
1415 |
ASSERT(!scratch2().is(reg)); |
|
1416 | 1418 |
// Push data from ExecutableAccessorInfo. |
1417 | 1419 |
if (isolate()->heap()->InNewSpace(callback->data())) { |
1418 |
Register scratch = reg.is(scratch1()) ? receiver() : scratch1();
|
|
1419 |
__ mov(scratch, Immediate(callback)); |
|
1420 |
__ push(FieldOperand(scratch, ExecutableAccessorInfo::kDataOffset)); |
|
1420 |
ASSERT(!scratch2().is(reg));
|
|
1421 |
__ mov(scratch2(), Immediate(callback));
|
|
1422 |
__ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset));
|
|
1421 | 1423 |
} else { |
1422 | 1424 |
__ push(Immediate(Handle<Object>(callback->data(), isolate()))); |
1423 | 1425 |
} |
... | ... | |
1427 | 1429 |
__ push(Immediate(reinterpret_cast<int>(isolate()))); |
1428 | 1430 |
__ push(reg); // holder |
1429 | 1431 |
|
1430 |
// Save a pointer to where we pushed the arguments pointer. This will be
|
|
1431 |
// passed as the const ExecutableAccessorInfo& to the C++ callback.
|
|
1432 |
__ push(scratch2());
|
|
1432 |
// Save a pointer to where we pushed the arguments. This will be
|
|
1433 |
// passed as the const PropertyAccessorInfo& to the C++ callback.
|
|
1434 |
__ push(esp);
|
|
1433 | 1435 |
|
1434 | 1436 |
__ push(name()); // name |
1435 | 1437 |
__ mov(ebx, esp); // esp points to reference to name (handler). |
... | ... | |
1460 | 1462 |
thunk_address, |
1461 | 1463 |
ApiParameterOperand(2), |
1462 | 1464 |
kStackSpace, |
1463 |
7); |
|
1465 |
Operand(ebp, 7 * kPointerSize), |
|
1466 |
NULL); |
|
1464 | 1467 |
} |
1465 | 1468 |
|
1466 | 1469 |
|
1467 |
void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
1470 |
void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
|
1468 | 1471 |
// Return the constant value. |
1469 | 1472 |
__ LoadObject(eax, value); |
1470 | 1473 |
__ ret(0); |
1471 | 1474 |
} |
1472 | 1475 |
|
1473 | 1476 |
|
1474 |
void BaseLoadStubCompiler::GenerateLoadInterceptor(
|
|
1477 |
void LoadStubCompiler::GenerateLoadInterceptor( |
|
1475 | 1478 |
Register holder_reg, |
1476 | 1479 |
Handle<JSObject> object, |
1477 | 1480 |
Handle<JSObject> interceptor_holder, |
... | ... | |
2394 | 2397 |
// Check if the argument is a heap number and load its value into xmm0. |
2395 | 2398 |
Label slow; |
2396 | 2399 |
__ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
2397 |
__ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
|
|
2400 |
__ movsd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
|
|
2398 | 2401 |
|
2399 | 2402 |
// Check if the argument is strictly positive. Note this also |
2400 | 2403 |
// discards NaN. |
... | ... | |
2444 | 2447 |
|
2445 | 2448 |
// Return a new heap number. |
2446 | 2449 |
__ AllocateHeapNumber(eax, ebx, edx, &slow); |
2447 |
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
|
2450 |
__ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
|
2448 | 2451 |
__ ret(2 * kPointerSize); |
2449 | 2452 |
|
2450 | 2453 |
// Return the argument (when it's an already round heap number). |
... | ... | |
2623 | 2626 |
|
2624 | 2627 |
// esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2625 | 2628 |
// duplicate of return address and will be overwritten. |
2626 |
GenerateFastApiCall(masm(), optimization, argc); |
|
2629 |
GenerateFastApiCall(masm(), optimization, argc, false);
|
|
2627 | 2630 |
|
2628 | 2631 |
__ bind(&miss); |
2629 | 2632 |
__ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
... | ... | |
3111 | 3114 |
|
3112 | 3115 |
|
3113 | 3116 |
void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
3117 |
Register receiver, |
|
3114 | 3118 |
Handle<JSFunction> getter) { |
3115 |
// ----------- S t a t e ------------- |
|
3116 |
// -- ecx : name |
|
3117 |
// -- edx : receiver |
|
3118 |
// -- esp[0] : return address |
|
3119 |
// ----------------------------------- |
|
3120 | 3119 |
{ |
3121 | 3120 |
FrameScope scope(masm, StackFrame::INTERNAL); |
3122 | 3121 |
|
3123 | 3122 |
if (!getter.is_null()) { |
3124 | 3123 |
// Call the JavaScript getter with the receiver on the stack. |
3125 |
__ push(edx);
|
|
3124 |
__ push(receiver);
|
|
3126 | 3125 |
ParameterCount actual(0); |
3127 | 3126 |
ParameterCount expected(getter); |
3128 | 3127 |
__ InvokeFunction(getter, expected, actual, |
Also available in: Unified diff