| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 STATIC_ASSERT(kNotStringTag != 0); | 322 STATIC_ASSERT(kNotStringTag != 0); |
| 323 __ test(scratch, Immediate(kNotStringTag)); | 323 __ test(scratch, Immediate(kNotStringTag)); |
| 324 __ j(not_zero, non_string_object); | 324 __ j(not_zero, non_string_object); |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 328 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
| 329 Register receiver, | 329 Register receiver, |
| 330 Register scratch1, | 330 Register scratch1, |
| 331 Register scratch2, | 331 Register scratch2, |
| 332 Label* miss, | 332 Label* miss) { |
| 333 bool support_wrappers) { | |
| 334 Label check_wrapper; | 333 Label check_wrapper; |
| 335 | 334 |
| 336 // Check if the object is a string leaving the instance type in the | 335 // Check if the object is a string leaving the instance type in the |
| 337 // scratch register. | 336 // scratch register. |
| 338 GenerateStringCheck(masm, receiver, scratch1, miss, | 337 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); |
| 339 support_wrappers ? &check_wrapper : miss); | |
| 340 | 338 |
| 341 // Load length from the string and convert to a smi. | 339 // Load length from the string and convert to a smi. |
| 342 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 340 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
| 343 __ ret(0); | 341 __ ret(0); |
| 344 | 342 |
| 345 if (support_wrappers) { | 343 // Check if the object is a JSValue wrapper. |
| 346 // Check if the object is a JSValue wrapper. | 344 __ bind(&check_wrapper); |
| 347 __ bind(&check_wrapper); | 345 __ cmp(scratch1, JS_VALUE_TYPE); |
| 348 __ cmp(scratch1, JS_VALUE_TYPE); | 346 __ j(not_equal, miss); |
| 349 __ j(not_equal, miss); | |
| 350 | 347 |
| 351 // Check if the wrapped value is a string and load the length | 348 // Check if the wrapped value is a string and load the length |
| 352 // directly if it is. | 349 // directly if it is. |
| 353 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 350 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
| 354 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 351 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
| 355 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); | 352 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
| 356 __ ret(0); | 353 __ ret(0); |
| 357 } | |
| 358 } | 354 } |
| 359 | 355 |
| 360 | 356 |
| 361 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 357 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 362 Register receiver, | 358 Register receiver, |
| 363 Register scratch1, | 359 Register scratch1, |
| 364 Register scratch2, | 360 Register scratch2, |
| 365 Label* miss_label) { | 361 Label* miss_label) { |
| 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 362 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 367 __ mov(eax, scratch1); | 363 __ mov(eax, scratch1); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 385 } | 381 } |
| 386 __ mov(dst, FieldOperand(src, offset)); | 382 __ mov(dst, FieldOperand(src, offset)); |
| 387 } | 383 } |
| 388 | 384 |
| 389 | 385 |
| 390 static void PushInterceptorArguments(MacroAssembler* masm, | 386 static void PushInterceptorArguments(MacroAssembler* masm, |
| 391 Register receiver, | 387 Register receiver, |
| 392 Register holder, | 388 Register holder, |
| 393 Register name, | 389 Register name, |
| 394 Handle<JSObject> holder_obj) { | 390 Handle<JSObject> holder_obj) { |
| 391 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 392 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 393 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 394 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 395 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| 395 __ push(name); | 396 __ push(name); |
| 396 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 397 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 397 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 398 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 398 Register scratch = name; | 399 Register scratch = name; |
| 399 __ mov(scratch, Immediate(interceptor)); | 400 __ mov(scratch, Immediate(interceptor)); |
| 400 __ push(scratch); | 401 __ push(scratch); |
| 401 __ push(receiver); | 402 __ push(receiver); |
| 402 __ push(holder); | 403 __ push(holder); |
| 403 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); | |
| 404 __ push(Immediate(reinterpret_cast<int>(masm->isolate()))); | |
| 405 } | 404 } |
| 406 | 405 |
| 407 | 406 |
| 408 static void CompileCallLoadPropertyWithInterceptor( | 407 static void CompileCallLoadPropertyWithInterceptor( |
| 409 MacroAssembler* masm, | 408 MacroAssembler* masm, |
| 410 Register receiver, | 409 Register receiver, |
| 411 Register holder, | 410 Register holder, |
| 412 Register name, | 411 Register name, |
| 413 Handle<JSObject> holder_obj) { | 412 Handle<JSObject> holder_obj) { |
| 414 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 413 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 415 __ CallExternalReference( | 414 __ CallExternalReference( |
| 416 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 415 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
| 417 masm->isolate()), | 416 masm->isolate()), |
| 418 6); | 417 StubCache::kInterceptorArgsLength); |
| 419 } | 418 } |
| 420 | 419 |
| 421 | 420 |
| 422 // Number of pointers to be reserved on stack for fast API call. | 421 // Number of pointers to be reserved on stack for fast API call. |
| 423 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 422 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 424 | 423 |
| 425 | 424 |
| 426 // Reserves space for the extra arguments to API function in the | 425 // Reserves space for the extra arguments to API function in the |
| 427 // caller's frame. | 426 // caller's frame. |
| 428 // | 427 // |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 | 725 |
| 727 FrameScope scope(masm, StackFrame::INTERNAL); | 726 FrameScope scope(masm, StackFrame::INTERNAL); |
| 728 // Save the name_ register across the call. | 727 // Save the name_ register across the call. |
| 729 __ push(name_); | 728 __ push(name_); |
| 730 | 729 |
| 731 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 730 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 732 | 731 |
| 733 __ CallExternalReference( | 732 __ CallExternalReference( |
| 734 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 733 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 735 masm->isolate()), | 734 masm->isolate()), |
| 736 6); | 735 StubCache::kInterceptorArgsLength); |
| 737 | 736 |
| 738 // Restore the name_ register. | 737 // Restore the name_ register. |
| 739 __ pop(name_); | 738 __ pop(name_); |
| 740 | 739 |
| 741 // Leave the internal frame. | 740 // Leave the internal frame. |
| 742 } | 741 } |
| 743 | 742 |
| 744 void LoadWithInterceptor(MacroAssembler* masm, | 743 void LoadWithInterceptor(MacroAssembler* masm, |
| 745 Register receiver, | 744 Register receiver, |
| 746 Register holder, | 745 Register holder, |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 851 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 853 __ JumpIfSmi(value_reg, miss_label); | 852 __ JumpIfSmi(value_reg, miss_label); |
| 854 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 853 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 855 Label do_store, heap_number; | 854 Label do_store, heap_number; |
| 856 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); | 855 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); |
| 857 | 856 |
| 858 __ JumpIfNotSmi(value_reg, &heap_number); | 857 __ JumpIfNotSmi(value_reg, &heap_number); |
| 859 __ SmiUntag(value_reg); | 858 __ SmiUntag(value_reg); |
| 860 if (CpuFeatures::IsSupported(SSE2)) { | 859 if (CpuFeatures::IsSupported(SSE2)) { |
| 861 CpuFeatureScope use_sse2(masm, SSE2); | 860 CpuFeatureScope use_sse2(masm, SSE2); |
| 862 __ cvtsi2sd(xmm0, value_reg); | 861 __ Cvtsi2sd(xmm0, value_reg); |
| 863 } else { | 862 } else { |
| 864 __ push(value_reg); | 863 __ push(value_reg); |
| 865 __ fild_s(Operand(esp, 0)); | 864 __ fild_s(Operand(esp, 0)); |
| 866 __ pop(value_reg); | 865 __ pop(value_reg); |
| 867 } | 866 } |
| 868 __ SmiTag(value_reg); | 867 __ SmiTag(value_reg); |
| 869 __ jmp(&do_store); | 868 __ jmp(&do_store); |
| 870 | 869 |
| 871 __ bind(&heap_number); | 870 __ bind(&heap_number); |
| 872 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 871 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 1030 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 1032 __ mov(scratch1, FieldOperand(scratch1, offset)); | 1031 __ mov(scratch1, FieldOperand(scratch1, offset)); |
| 1033 } | 1032 } |
| 1034 | 1033 |
| 1035 // Store the value into the storage. | 1034 // Store the value into the storage. |
| 1036 Label do_store, heap_number; | 1035 Label do_store, heap_number; |
| 1037 __ JumpIfNotSmi(value_reg, &heap_number); | 1036 __ JumpIfNotSmi(value_reg, &heap_number); |
| 1038 __ SmiUntag(value_reg); | 1037 __ SmiUntag(value_reg); |
| 1039 if (CpuFeatures::IsSupported(SSE2)) { | 1038 if (CpuFeatures::IsSupported(SSE2)) { |
| 1040 CpuFeatureScope use_sse2(masm, SSE2); | 1039 CpuFeatureScope use_sse2(masm, SSE2); |
| 1041 __ cvtsi2sd(xmm0, value_reg); | 1040 __ Cvtsi2sd(xmm0, value_reg); |
| 1042 } else { | 1041 } else { |
| 1043 __ push(value_reg); | 1042 __ push(value_reg); |
| 1044 __ fild_s(Operand(esp, 0)); | 1043 __ fild_s(Operand(esp, 0)); |
| 1045 __ pop(value_reg); | 1044 __ pop(value_reg); |
| 1046 } | 1045 } |
| 1047 __ SmiTag(value_reg); | 1046 __ SmiTag(value_reg); |
| 1048 __ jmp(&do_store); | 1047 __ jmp(&do_store); |
| 1049 __ bind(&heap_number); | 1048 __ bind(&heap_number); |
| 1050 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 1049 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 1051 miss_label, DONT_DO_SMI_CHECK); | 1050 miss_label, DONT_DO_SMI_CHECK); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1394 } | 1393 } |
| 1395 | 1394 |
| 1396 | 1395 |
| 1397 void BaseLoadStubCompiler::GenerateLoadCallback( | 1396 void BaseLoadStubCompiler::GenerateLoadCallback( |
| 1398 Register reg, | 1397 Register reg, |
| 1399 Handle<ExecutableAccessorInfo> callback) { | 1398 Handle<ExecutableAccessorInfo> callback) { |
| 1400 // Insert additional parameters into the stack frame above return address. | 1399 // Insert additional parameters into the stack frame above return address. |
| 1401 ASSERT(!scratch3().is(reg)); | 1400 ASSERT(!scratch3().is(reg)); |
| 1402 __ pop(scratch3()); // Get return address to place it below. | 1401 __ pop(scratch3()); // Get return address to place it below. |
| 1403 | 1402 |
| 1403 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 0); |
| 1404 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == -1); |
| 1405 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == -2); |
| 1406 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == -3); |
| 1407 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == -4); |
| 1408 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == -5); |
| 1404 __ push(receiver()); // receiver | 1409 __ push(receiver()); // receiver |
| 1405 __ mov(scratch2(), esp); | 1410 __ mov(scratch2(), esp); |
| 1406 ASSERT(!scratch2().is(reg)); | 1411 ASSERT(!scratch2().is(reg)); |
| 1407 __ push(reg); // holder | |
| 1408 // Push data from ExecutableAccessorInfo. | 1412 // Push data from ExecutableAccessorInfo. |
| 1409 if (isolate()->heap()->InNewSpace(callback->data())) { | 1413 if (isolate()->heap()->InNewSpace(callback->data())) { |
| 1410 __ mov(scratch1(), Immediate(callback)); | 1414 Register scratch = reg.is(scratch1()) ? receiver() : scratch1(); |
| 1411 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); | 1415 __ mov(scratch, Immediate(callback)); |
| 1416 __ push(FieldOperand(scratch, ExecutableAccessorInfo::kDataOffset)); |
| 1412 } else { | 1417 } else { |
| 1413 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 1418 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); |
| 1414 } | 1419 } |
| 1415 __ push(Immediate(isolate()->factory()->undefined_value())); // ReturnValue | 1420 __ push(Immediate(isolate()->factory()->undefined_value())); // ReturnValue |
| 1416 // ReturnValue default value | 1421 // ReturnValue default value |
| 1417 __ push(Immediate(isolate()->factory()->undefined_value())); | 1422 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 1418 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1423 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
| 1424 __ push(reg); // holder |
| 1419 | 1425 |
| 1420 // Save a pointer to where we pushed the arguments pointer. This will be | 1426 // Save a pointer to where we pushed the arguments pointer. This will be |
| 1421 // passed as the const ExecutableAccessorInfo& to the C++ callback. | 1427 // passed as the const ExecutableAccessorInfo& to the C++ callback. |
| 1422 __ push(scratch2()); | 1428 __ push(scratch2()); |
| 1423 | 1429 |
| 1424 __ push(name()); // name | 1430 __ push(name()); // name |
| 1425 __ mov(ebx, esp); // esp points to reference to name (handler). | 1431 __ mov(ebx, esp); // esp points to reference to name (handler). |
| 1426 | 1432 |
| 1427 __ push(scratch3()); // Restore return address. | 1433 __ push(scratch3()); // Restore return address. |
| 1428 | 1434 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1443 // already generated). Do not allow the assembler to perform a | 1449 // already generated). Do not allow the assembler to perform a |
| 1444 // garbage collection but instead return the allocation failure | 1450 // garbage collection but instead return the allocation failure |
| 1445 // object. | 1451 // object. |
| 1446 | 1452 |
| 1447 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1453 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
| 1448 | 1454 |
| 1449 __ CallApiFunctionAndReturn(getter_address, | 1455 __ CallApiFunctionAndReturn(getter_address, |
| 1450 thunk_address, | 1456 thunk_address, |
| 1451 ApiParameterOperand(2), | 1457 ApiParameterOperand(2), |
| 1452 kStackSpace, | 1458 kStackSpace, |
| 1453 6); | 1459 7); |
| 1454 } | 1460 } |
| 1455 | 1461 |
| 1456 | 1462 |
| 1457 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1463 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1458 // Return the constant value. | 1464 // Return the constant value. |
| 1459 __ LoadObject(eax, value); | 1465 __ LoadObject(eax, value); |
| 1460 __ ret(0); | 1466 __ ret(0); |
| 1461 } | 1467 } |
| 1462 | 1468 |
| 1463 | 1469 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 // Call the runtime system to load the interceptor. | 1556 // Call the runtime system to load the interceptor. |
| 1551 // Check that the maps haven't changed. | 1557 // Check that the maps haven't changed. |
| 1552 __ pop(scratch2()); // save old return address | 1558 __ pop(scratch2()); // save old return address |
| 1553 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1559 PushInterceptorArguments(masm(), receiver(), holder_reg, |
| 1554 this->name(), interceptor_holder); | 1560 this->name(), interceptor_holder); |
| 1555 __ push(scratch2()); // restore old return address | 1561 __ push(scratch2()); // restore old return address |
| 1556 | 1562 |
| 1557 ExternalReference ref = | 1563 ExternalReference ref = |
| 1558 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1564 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1559 isolate()); | 1565 isolate()); |
| 1560 __ TailCallExternalReference(ref, 6, 1); | 1566 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
| 1561 } | 1567 } |
| 1562 } | 1568 } |
| 1563 | 1569 |
| 1564 | 1570 |
| 1565 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1571 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1566 if (kind_ == Code::KEYED_CALL_IC) { | 1572 if (kind_ == Code::KEYED_CALL_IC) { |
| 1567 __ cmp(ecx, Immediate(name)); | 1573 __ cmp(ecx, Immediate(name)); |
| 1568 __ j(not_equal, miss); | 1574 __ j(not_equal, miss); |
| 1569 } | 1575 } |
| 1570 } | 1576 } |
| (...skipping 1687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3258 // ----------------------------------- | 3264 // ----------------------------------- |
| 3259 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3265 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3260 } | 3266 } |
| 3261 | 3267 |
| 3262 | 3268 |
| 3263 #undef __ | 3269 #undef __ |
| 3264 | 3270 |
| 3265 } } // namespace v8::internal | 3271 } } // namespace v8::internal |
| 3266 | 3272 |
| 3267 #endif // V8_TARGET_ARCH_IA32 | 3273 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |