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) { |
333 Label check_wrapper; | 334 Label check_wrapper; |
334 | 335 |
335 // Check if the object is a string leaving the instance type in the | 336 // Check if the object is a string leaving the instance type in the |
336 // scratch register. | 337 // scratch register. |
337 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); | 338 GenerateStringCheck(masm, receiver, scratch1, miss, |
| 339 support_wrappers ? &check_wrapper : miss); |
338 | 340 |
339 // Load length from the string and convert to a smi. | 341 // Load length from the string and convert to a smi. |
340 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 342 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
341 __ ret(0); | 343 __ ret(0); |
342 | 344 |
343 // Check if the object is a JSValue wrapper. | 345 if (support_wrappers) { |
344 __ bind(&check_wrapper); | 346 // Check if the object is a JSValue wrapper. |
345 __ cmp(scratch1, JS_VALUE_TYPE); | 347 __ bind(&check_wrapper); |
346 __ j(not_equal, miss); | 348 __ cmp(scratch1, JS_VALUE_TYPE); |
| 349 __ j(not_equal, miss); |
347 | 350 |
348 // Check if the wrapped value is a string and load the length | 351 // Check if the wrapped value is a string and load the length |
349 // directly if it is. | 352 // directly if it is. |
350 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 353 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
351 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 354 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
352 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); | 355 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
353 __ ret(0); | 356 __ ret(0); |
| 357 } |
354 } | 358 } |
355 | 359 |
356 | 360 |
357 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 361 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
358 Register receiver, | 362 Register receiver, |
359 Register scratch1, | 363 Register scratch1, |
360 Register scratch2, | 364 Register scratch2, |
361 Label* miss_label) { | 365 Label* miss_label) { |
362 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
363 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 // ----------------------------------- | 455 // ----------------------------------- |
452 __ pop(scratch); | 456 __ pop(scratch); |
453 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); | 457 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); |
454 __ push(scratch); | 458 __ push(scratch); |
455 } | 459 } |
456 | 460 |
457 | 461 |
458 // Generates call to API function. | 462 // Generates call to API function. |
459 static void GenerateFastApiCall(MacroAssembler* masm, | 463 static void GenerateFastApiCall(MacroAssembler* masm, |
460 const CallOptimization& optimization, | 464 const CallOptimization& optimization, |
461 int argc, | 465 int argc) { |
462 bool restore_context) { | |
463 // ----------- S t a t e ------------- | 466 // ----------- S t a t e ------------- |
464 // -- esp[0] : return address | 467 // -- esp[0] : return address |
465 // -- esp[4] : context | 468 // -- esp[4] : object passing the type check |
466 // -- esp[8] : object passing the type check | |
467 // (last fast api call extra argument, | 469 // (last fast api call extra argument, |
468 // set by CheckPrototypes) | 470 // set by CheckPrototypes) |
469 // -- esp[12] : api function | 471 // -- esp[8] : api function |
470 // (first fast api call extra argument) | 472 // (first fast api call extra argument) |
471 // -- esp[16] : api call data | 473 // -- esp[12] : api call data |
472 // -- esp[20] : isolate | 474 // -- esp[16] : isolate |
473 // -- esp[24] : ReturnValue default value | 475 // -- esp[20] : ReturnValue default value |
474 // -- esp[28] : ReturnValue | 476 // -- esp[24] : ReturnValue |
475 // -- esp[32] : last argument | 477 // -- esp[28] : last argument |
476 // -- ... | 478 // -- ... |
477 // -- esp[(argc + 7) * 4] : first argument | 479 // -- esp[(argc + 6) * 4] : first argument |
478 // -- esp[(argc + 8) * 4] : receiver | 480 // -- esp[(argc + 7) * 4] : receiver |
479 // ----------------------------------- | 481 // ----------------------------------- |
480 | |
481 // Save calling context. | |
482 __ mov(Operand(esp, kPointerSize), esi); | |
483 | |
484 // Get the function and setup the context. | 482 // Get the function and setup the context. |
485 Handle<JSFunction> function = optimization.constant_function(); | 483 Handle<JSFunction> function = optimization.constant_function(); |
486 __ LoadHeapObject(edi, function); | 484 __ LoadHeapObject(edi, function); |
487 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 485 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
488 | 486 |
489 // Pass the additional arguments. | 487 // Pass the additional arguments. |
490 __ mov(Operand(esp, 3 * kPointerSize), edi); | 488 __ mov(Operand(esp, 2 * kPointerSize), edi); |
491 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 489 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
492 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 490 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
493 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 491 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
494 __ mov(ecx, api_call_info); | 492 __ mov(ecx, api_call_info); |
495 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 493 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
496 __ mov(Operand(esp, 4 * kPointerSize), ebx); | 494 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
497 } else { | 495 } else { |
498 __ mov(Operand(esp, 4 * kPointerSize), Immediate(call_data)); | 496 __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); |
499 } | 497 } |
| 498 __ mov(Operand(esp, 4 * kPointerSize), |
| 499 Immediate(reinterpret_cast<int>(masm->isolate()))); |
500 __ mov(Operand(esp, 5 * kPointerSize), | 500 __ mov(Operand(esp, 5 * kPointerSize), |
501 Immediate(reinterpret_cast<int>(masm->isolate()))); | 501 masm->isolate()->factory()->undefined_value()); |
502 __ mov(Operand(esp, 6 * kPointerSize), | 502 __ mov(Operand(esp, 6 * kPointerSize), |
503 masm->isolate()->factory()->undefined_value()); | 503 masm->isolate()->factory()->undefined_value()); |
504 __ mov(Operand(esp, 7 * kPointerSize), | |
505 masm->isolate()->factory()->undefined_value()); | |
506 | 504 |
507 // Prepare arguments. | 505 // Prepare arguments. |
508 STATIC_ASSERT(kFastApiCallArguments == 7); | 506 STATIC_ASSERT(kFastApiCallArguments == 6); |
509 __ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 507 __ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
510 | 508 |
511 | 509 |
512 // API function gets reference to the v8::Arguments. If CPU profiler | 510 // API function gets reference to the v8::Arguments. If CPU profiler |
513 // is enabled wrapper function will be called and we need to pass | 511 // is enabled wrapper function will be called and we need to pass |
514 // address of the callback as additional parameter, always allocate | 512 // address of the callback as additional parameter, always allocate |
515 // space for it. | 513 // space for it. |
516 const int kApiArgc = 1 + 1; | 514 const int kApiArgc = 1 + 1; |
517 | 515 |
518 // Allocate the v8::Arguments structure in the arguments' space since | 516 // Allocate the v8::Arguments structure in the arguments' space since |
(...skipping 13 matching lines...) Expand all Loading... |
532 __ Set(ApiParameterOperand(4), Immediate(argc)); | 530 __ Set(ApiParameterOperand(4), Immediate(argc)); |
533 // v8::Arguments::is_construct_call_. | 531 // v8::Arguments::is_construct_call_. |
534 __ Set(ApiParameterOperand(5), Immediate(0)); | 532 __ Set(ApiParameterOperand(5), Immediate(0)); |
535 | 533 |
536 // v8::InvocationCallback's argument. | 534 // v8::InvocationCallback's argument. |
537 __ lea(eax, ApiParameterOperand(2)); | 535 __ lea(eax, ApiParameterOperand(2)); |
538 __ mov(ApiParameterOperand(0), eax); | 536 __ mov(ApiParameterOperand(0), eax); |
539 | 537 |
540 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 538 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
541 | 539 |
542 Operand context_restore_operand(ebp, 2 * kPointerSize); | |
543 Operand return_value_operand( | |
544 ebp, (kFastApiCallArguments + 1) * kPointerSize); | |
545 __ CallApiFunctionAndReturn(function_address, | 540 __ CallApiFunctionAndReturn(function_address, |
546 thunk_address, | 541 thunk_address, |
547 ApiParameterOperand(1), | 542 ApiParameterOperand(1), |
548 argc + kFastApiCallArguments + 1, | 543 argc + kFastApiCallArguments + 1, |
549 return_value_operand, | 544 kFastApiCallArguments + 1); |
550 restore_context ? | |
551 &context_restore_operand : NULL); | |
552 } | 545 } |
553 | 546 |
554 | 547 |
555 // Generate call to api function. | 548 // Generate call to api function. |
556 static void GenerateFastApiCall(MacroAssembler* masm, | 549 static void GenerateFastApiCall(MacroAssembler* masm, |
557 const CallOptimization& optimization, | 550 const CallOptimization& optimization, |
558 Register receiver, | 551 Register receiver, |
559 Register scratch, | 552 Register scratch, |
560 int argc, | 553 int argc, |
561 Register* values) { | 554 Register* values) { |
562 ASSERT(optimization.is_simple_api_call()); | 555 ASSERT(optimization.is_simple_api_call()); |
563 ASSERT(!receiver.is(scratch)); | 556 ASSERT(!receiver.is(scratch)); |
564 | 557 |
565 const int stack_space = kFastApiCallArguments + argc + 1; | 558 const int stack_space = kFastApiCallArguments + argc + 1; |
566 const int kHolderIndex = kFastApiCallArguments + | |
567 FunctionCallbackArguments::kHolderIndex; | |
568 // Copy return value. | 559 // Copy return value. |
569 __ mov(scratch, Operand(esp, 0)); | 560 __ mov(scratch, Operand(esp, 0)); |
570 // Assign stack space for the call arguments. | 561 // Assign stack space for the call arguments. |
571 __ sub(esp, Immediate(stack_space * kPointerSize)); | 562 __ sub(esp, Immediate(stack_space * kPointerSize)); |
572 // Move the return address on top of the stack. | 563 // Move the return address on top of the stack. |
573 __ mov(Operand(esp, 0), scratch); | 564 __ mov(Operand(esp, 0), scratch); |
574 // Write holder to stack frame. | 565 // Write holder to stack frame. |
575 __ mov(Operand(esp, kHolderIndex * kPointerSize), receiver); | 566 __ mov(Operand(esp, 1 * kPointerSize), receiver); |
576 // Write receiver to stack frame. | 567 // Write receiver to stack frame. |
577 int index = stack_space; | 568 int index = stack_space; |
578 __ mov(Operand(esp, index-- * kPointerSize), receiver); | 569 __ mov(Operand(esp, index-- * kPointerSize), receiver); |
579 // Write the arguments to stack frame. | 570 // Write the arguments to stack frame. |
580 for (int i = 0; i < argc; i++) { | 571 for (int i = 0; i < argc; i++) { |
581 ASSERT(!receiver.is(values[i])); | 572 ASSERT(!receiver.is(values[i])); |
582 ASSERT(!scratch.is(values[i])); | 573 ASSERT(!scratch.is(values[i])); |
583 __ mov(Operand(esp, index-- * kPointerSize), values[i]); | 574 __ mov(Operand(esp, index-- * kPointerSize), values[i]); |
584 } | 575 } |
585 | 576 |
586 GenerateFastApiCall(masm, optimization, argc, true); | 577 GenerateFastApiCall(masm, optimization, argc); |
587 } | 578 } |
588 | 579 |
589 | 580 |
590 class CallInterceptorCompiler BASE_EMBEDDED { | 581 class CallInterceptorCompiler BASE_EMBEDDED { |
591 public: | 582 public: |
592 CallInterceptorCompiler(StubCompiler* stub_compiler, | 583 CallInterceptorCompiler(StubCompiler* stub_compiler, |
593 const ParameterCount& arguments, | 584 const ParameterCount& arguments, |
594 Register name, | 585 Register name, |
595 Code::ExtraICState extra_state) | 586 Code::ExtraICState extra_state) |
596 : stub_compiler_(stub_compiler), | 587 : stub_compiler_(stub_compiler), |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 } else { | 681 } else { |
691 // CheckPrototypes has a side effect of fetching a 'holder' | 682 // CheckPrototypes has a side effect of fetching a 'holder' |
692 // for API (object which is instanceof for the signature). It's | 683 // for API (object which is instanceof for the signature). It's |
693 // safe to omit it here, as if present, it should be fetched | 684 // safe to omit it here, as if present, it should be fetched |
694 // by the previous CheckPrototypes. | 685 // by the previous CheckPrototypes. |
695 ASSERT(depth2 == kInvalidProtoDepth); | 686 ASSERT(depth2 == kInvalidProtoDepth); |
696 } | 687 } |
697 | 688 |
698 // Invoke function. | 689 // Invoke function. |
699 if (can_do_fast_api_call) { | 690 if (can_do_fast_api_call) { |
700 GenerateFastApiCall(masm, optimization, arguments_.immediate(), false); | 691 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
701 } else { | 692 } else { |
702 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 693 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
703 ? CALL_AS_FUNCTION | 694 ? CALL_AS_FUNCTION |
704 : CALL_AS_METHOD; | 695 : CALL_AS_METHOD; |
705 Handle<JSFunction> function = optimization.constant_function(); | 696 Handle<JSFunction> function = optimization.constant_function(); |
706 ParameterCount expected(function); | 697 ParameterCount expected(function); |
707 __ InvokeFunction(function, expected, arguments_, | 698 __ InvokeFunction(function, expected, arguments_, |
708 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 699 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
709 } | 700 } |
710 | 701 |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 855 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
865 __ JumpIfSmi(value_reg, miss_label); | 856 __ JumpIfSmi(value_reg, miss_label); |
866 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 857 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
867 Label do_store, heap_number; | 858 Label do_store, heap_number; |
868 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); | 859 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); |
869 | 860 |
870 __ JumpIfNotSmi(value_reg, &heap_number); | 861 __ JumpIfNotSmi(value_reg, &heap_number); |
871 __ SmiUntag(value_reg); | 862 __ SmiUntag(value_reg); |
872 if (CpuFeatures::IsSupported(SSE2)) { | 863 if (CpuFeatures::IsSupported(SSE2)) { |
873 CpuFeatureScope use_sse2(masm, SSE2); | 864 CpuFeatureScope use_sse2(masm, SSE2); |
874 __ Cvtsi2sd(xmm0, value_reg); | 865 __ cvtsi2sd(xmm0, value_reg); |
875 } else { | 866 } else { |
876 __ push(value_reg); | 867 __ push(value_reg); |
877 __ fild_s(Operand(esp, 0)); | 868 __ fild_s(Operand(esp, 0)); |
878 __ pop(value_reg); | 869 __ pop(value_reg); |
879 } | 870 } |
880 __ SmiTag(value_reg); | 871 __ SmiTag(value_reg); |
881 __ jmp(&do_store); | 872 __ jmp(&do_store); |
882 | 873 |
883 __ bind(&heap_number); | 874 __ bind(&heap_number); |
884 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 875 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 1034 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
1044 __ mov(scratch1, FieldOperand(scratch1, offset)); | 1035 __ mov(scratch1, FieldOperand(scratch1, offset)); |
1045 } | 1036 } |
1046 | 1037 |
1047 // Store the value into the storage. | 1038 // Store the value into the storage. |
1048 Label do_store, heap_number; | 1039 Label do_store, heap_number; |
1049 __ JumpIfNotSmi(value_reg, &heap_number); | 1040 __ JumpIfNotSmi(value_reg, &heap_number); |
1050 __ SmiUntag(value_reg); | 1041 __ SmiUntag(value_reg); |
1051 if (CpuFeatures::IsSupported(SSE2)) { | 1042 if (CpuFeatures::IsSupported(SSE2)) { |
1052 CpuFeatureScope use_sse2(masm, SSE2); | 1043 CpuFeatureScope use_sse2(masm, SSE2); |
1053 __ Cvtsi2sd(xmm0, value_reg); | 1044 __ cvtsi2sd(xmm0, value_reg); |
1054 } else { | 1045 } else { |
1055 __ push(value_reg); | 1046 __ push(value_reg); |
1056 __ fild_s(Operand(esp, 0)); | 1047 __ fild_s(Operand(esp, 0)); |
1057 __ pop(value_reg); | 1048 __ pop(value_reg); |
1058 } | 1049 } |
1059 __ SmiTag(value_reg); | 1050 __ SmiTag(value_reg); |
1060 __ jmp(&do_store); | 1051 __ jmp(&do_store); |
1061 __ bind(&heap_number); | 1052 __ bind(&heap_number); |
1062 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 1053 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
1063 miss_label, DONT_DO_SMI_CHECK); | 1054 miss_label, DONT_DO_SMI_CHECK); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1153 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1163 Register object_reg, | 1154 Register object_reg, |
1164 Handle<JSObject> holder, | 1155 Handle<JSObject> holder, |
1165 Register holder_reg, | 1156 Register holder_reg, |
1166 Register scratch1, | 1157 Register scratch1, |
1167 Register scratch2, | 1158 Register scratch2, |
1168 Handle<Name> name, | 1159 Handle<Name> name, |
1169 int save_at_depth, | 1160 int save_at_depth, |
1170 Label* miss, | 1161 Label* miss, |
1171 PrototypeCheckType check) { | 1162 PrototypeCheckType check) { |
1172 const int kHolderIndex = kFastApiCallArguments + | |
1173 FunctionCallbackArguments::kHolderIndex; | |
1174 // Make sure that the type feedback oracle harvests the receiver map. | 1163 // Make sure that the type feedback oracle harvests the receiver map. |
1175 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1164 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
1176 __ mov(scratch1, Handle<Map>(object->map())); | 1165 __ mov(scratch1, Handle<Map>(object->map())); |
1177 | 1166 |
1178 Handle<JSObject> first = object; | 1167 Handle<JSObject> first = object; |
1179 // Make sure there's no overlap between holder and object registers. | 1168 // Make sure there's no overlap between holder and object registers. |
1180 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1169 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1181 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1170 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1182 && !scratch2.is(scratch1)); | 1171 && !scratch2.is(scratch1)); |
1183 | 1172 |
1184 // Keep track of the current object in register reg. | 1173 // Keep track of the current object in register reg. |
1185 Register reg = object_reg; | 1174 Register reg = object_reg; |
1186 Handle<JSObject> current = object; | 1175 Handle<JSObject> current = object; |
1187 int depth = 0; | 1176 int depth = 0; |
1188 | 1177 |
1189 if (save_at_depth == depth) { | 1178 if (save_at_depth == depth) { |
1190 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1179 __ mov(Operand(esp, kPointerSize), reg); |
1191 } | 1180 } |
1192 | 1181 |
1193 // Traverse the prototype chain and check the maps in the prototype chain for | 1182 // Traverse the prototype chain and check the maps in the prototype chain for |
1194 // fast and global objects or do negative lookup for normal objects. | 1183 // fast and global objects or do negative lookup for normal objects. |
1195 while (!current.is_identical_to(holder)) { | 1184 while (!current.is_identical_to(holder)) { |
1196 ++depth; | 1185 ++depth; |
1197 | 1186 |
1198 // Only global objects and objects that do not require access | 1187 // Only global objects and objects that do not require access |
1199 // checks are allowed in stubs. | 1188 // checks are allowed in stubs. |
1200 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1189 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 // The prototype is in new space; we cannot store a reference to it | 1230 // The prototype is in new space; we cannot store a reference to it |
1242 // in the code. Load it from the map. | 1231 // in the code. Load it from the map. |
1243 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1232 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
1244 } else { | 1233 } else { |
1245 // The prototype is in old space; load it directly. | 1234 // The prototype is in old space; load it directly. |
1246 __ mov(reg, prototype); | 1235 __ mov(reg, prototype); |
1247 } | 1236 } |
1248 } | 1237 } |
1249 | 1238 |
1250 if (save_at_depth == depth) { | 1239 if (save_at_depth == depth) { |
1251 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1240 __ mov(Operand(esp, kPointerSize), reg); |
1252 } | 1241 } |
1253 | 1242 |
1254 // Go to the next object in the prototype chain. | 1243 // Go to the next object in the prototype chain. |
1255 current = prototype; | 1244 current = prototype; |
1256 } | 1245 } |
1257 ASSERT(current.is_identical_to(holder)); | 1246 ASSERT(current.is_identical_to(holder)); |
1258 | 1247 |
1259 // Log the check depth. | 1248 // Log the check depth. |
1260 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1249 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1261 | 1250 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 // already generated). Do not allow the assembler to perform a | 1453 // already generated). Do not allow the assembler to perform a |
1465 // garbage collection but instead return the allocation failure | 1454 // garbage collection but instead return the allocation failure |
1466 // object. | 1455 // object. |
1467 | 1456 |
1468 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1457 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
1469 | 1458 |
1470 __ CallApiFunctionAndReturn(getter_address, | 1459 __ CallApiFunctionAndReturn(getter_address, |
1471 thunk_address, | 1460 thunk_address, |
1472 ApiParameterOperand(2), | 1461 ApiParameterOperand(2), |
1473 kStackSpace, | 1462 kStackSpace, |
1474 Operand(ebp, 7 * kPointerSize), | 1463 7); |
1475 NULL); | |
1476 } | 1464 } |
1477 | 1465 |
1478 | 1466 |
1479 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1467 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1480 // Return the constant value. | 1468 // Return the constant value. |
1481 __ LoadObject(eax, value); | 1469 __ LoadObject(eax, value); |
1482 __ ret(0); | 1470 __ ret(0); |
1483 } | 1471 } |
1484 | 1472 |
1485 | 1473 |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2628 // Check that the maps haven't changed and find a Holder as a side effect. | 2616 // Check that the maps haven't changed and find a Holder as a side effect. |
2629 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2617 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2630 name, depth, &miss); | 2618 name, depth, &miss); |
2631 | 2619 |
2632 // Move the return address on top of the stack. | 2620 // Move the return address on top of the stack. |
2633 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2621 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
2634 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2622 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2635 | 2623 |
2636 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2624 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2637 // duplicate of return address and will be overwritten. | 2625 // duplicate of return address and will be overwritten. |
2638 GenerateFastApiCall(masm(), optimization, argc, false); | 2626 GenerateFastApiCall(masm(), optimization, argc); |
2639 | 2627 |
2640 __ bind(&miss); | 2628 __ bind(&miss); |
2641 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2629 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2642 | 2630 |
2643 __ bind(&miss_before_stack_reserved); | 2631 __ bind(&miss_before_stack_reserved); |
2644 GenerateMissBranch(); | 2632 GenerateMissBranch(); |
2645 | 2633 |
2646 // Return the generated code. | 2634 // Return the generated code. |
2647 return GetCode(function); | 2635 return GetCode(function); |
2648 } | 2636 } |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3280 // ----------------------------------- | 3268 // ----------------------------------- |
3281 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3269 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3282 } | 3270 } |
3283 | 3271 |
3284 | 3272 |
3285 #undef __ | 3273 #undef __ |
3286 | 3274 |
3287 } } // namespace v8::internal | 3275 } } // namespace v8::internal |
3288 | 3276 |
3289 #endif // V8_TARGET_ARCH_IA32 | 3277 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |