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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 10615002: Track allocation info (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Diff with b_e Created 8 years, 1 month 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
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 int length, 312 int length,
313 FastCloneShallowArrayStub::Mode mode, 313 FastCloneShallowArrayStub::Mode mode,
314 Label* fail) { 314 Label* fail) {
315 // Registers on entry: 315 // Registers on entry:
316 // 316 //
317 // ecx: boilerplate literal array. 317 // ecx: boilerplate literal array.
318 ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS); 318 ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS);
319 319
320 // All sizes here are multiples of kPointerSize. 320 // All sizes here are multiples of kPointerSize.
321 int elements_size = 0; 321 int elements_size = 0;
322 int allocation_site_info_size = 0;
322 if (length > 0) { 323 if (length > 0) {
323 elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 324 elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
324 ? FixedDoubleArray::SizeFor(length) 325 ? FixedDoubleArray::SizeFor(length)
325 : FixedArray::SizeFor(length); 326 : FixedArray::SizeFor(length);
327 } else {
328 // Empty or COW arrays need to track type information to adjust the
329 // boilerplate ElementsKind on subsequent stores.
330 allocation_site_info_size = AllocationSiteInfo::kSize;
326 } 331 }
327 int size = JSArray::kSize + elements_size; 332 int allocation_offset = JSArray::kSize + elements_size;
333 int size = allocation_offset + allocation_site_info_size;
328 334
329 // Allocate both the JS array and the elements array in one big 335 // Allocate both the JS array and the elements array in one big
330 // allocation. This avoids multiple limit checks. 336 // allocation. This avoids multiple limit checks.
331 __ AllocateInNewSpace(size, eax, ebx, edx, fail, TAG_OBJECT); 337 __ AllocateInNewSpace(size, eax, ebx, edx, fail, TAG_OBJECT);
332 338
333 // Copy the JS array part. 339 // Copy the JS array part.
334 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 340 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
335 if ((i != JSArray::kElementsOffset) || (length == 0)) { 341 if ((i != JSArray::kElementsOffset) || (length == 0)) {
336 __ mov(ebx, FieldOperand(ecx, i)); 342 __ mov(ebx, FieldOperand(ecx, i));
337 __ mov(FieldOperand(eax, i), ebx); 343 __ mov(FieldOperand(eax, i), ebx);
(...skipping 20 matching lines...) Expand all
358 __ mov(ebx, FieldOperand(ecx, i)); 364 __ mov(ebx, FieldOperand(ecx, i));
359 __ mov(FieldOperand(edx, i), ebx); 365 __ mov(FieldOperand(edx, i), ebx);
360 } 366 }
361 while (i < elements_size) { 367 while (i < elements_size) {
362 __ fld_d(FieldOperand(ecx, i)); 368 __ fld_d(FieldOperand(ecx, i));
363 __ fstp_d(FieldOperand(edx, i)); 369 __ fstp_d(FieldOperand(edx, i));
364 i += kDoubleSize; 370 i += kDoubleSize;
365 } 371 }
366 ASSERT(i == elements_size); 372 ASSERT(i == elements_size);
367 } 373 }
374 } else {
375 // Track information about the allocation site
376 __ mov(FieldOperand(eax, allocation_offset),
377 Immediate(Handle<Map>(masm->isolate()->heap()->
378 allocation_site_info_map())));
379 __ mov(FieldOperand(eax, allocation_offset + kPointerSize), ecx);
368 } 380 }
369 } 381 }
370 382
371 383
372 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 384 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
373 // Stack layout on entry: 385 // Stack layout on entry:
374 // 386 //
375 // [esp + kPointerSize]: constant elements. 387 // [esp + kPointerSize]: constant elements.
376 // [esp + (2 * kPointerSize)]: literal index. 388 // [esp + (2 * kPointerSize)]: literal index.
377 // [esp + (3 * kPointerSize)]: literals array. 389 // [esp + (3 * kPointerSize)]: literals array.
(...skipping 4298 matching lines...) Expand 10 before | Expand all | Expand 10 after
4676 } 4688 }
4677 4689
4678 4690
4679 static void GenerateRecordCallTarget(MacroAssembler* masm) { 4691 static void GenerateRecordCallTarget(MacroAssembler* masm) {
4680 // Cache the called function in a global property cell. Cache states 4692 // Cache the called function in a global property cell. Cache states
4681 // are uninitialized, monomorphic (indicated by a JSFunction), and 4693 // are uninitialized, monomorphic (indicated by a JSFunction), and
4682 // megamorphic. 4694 // megamorphic.
4683 // ebx : cache cell for call target 4695 // ebx : cache cell for call target
4684 // edi : the function to call 4696 // edi : the function to call
4685 Isolate* isolate = masm->isolate(); 4697 Isolate* isolate = masm->isolate();
4686 Label initialize, done; 4698 Label initialize, done, miss, megamorphic, not_array_function;
4687 4699
4688 // Load the cache state into ecx. 4700 // Load the cache state into ecx.
4689 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 4701 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
4690 4702
4691 // A monomorphic cache hit or an already megamorphic state: invoke the 4703 // A monomorphic cache hit or an already megamorphic state: invoke the
4692 // function without changing the state. 4704 // function without changing the state.
4693 __ cmp(ecx, edi); 4705 __ cmp(ecx, edi);
4694 __ j(equal, &done, Label::kNear); 4706 __ j(equal, &done, Label::kFar);
4695 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); 4707 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
4696 __ j(equal, &done, Label::kNear); 4708 __ j(equal, &done, Label::kFar);
4697 4709
4710 // Special handling of the Array() function, which caches not only the
4711 // monomorphic Array function but the initial ElementsKind with special
4712 // sentinels.
4713 Handle<Object> terminal_kind_sentinel =
4714 TypeFeedbackCells::MonomorphicArraySentinel(
4715 LAST_FAST_ELEMENTS_KIND);
4716 __ cmp(ecx, Immediate(terminal_kind_sentinel));
4717 __ j(above, &miss, Label::kFar);
4718 // Load the global or builtins object from the current context.
4719 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
4720 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset));
4721 // Make sure the function is the Array() function.
4722 __ cmp(edi, Operand(ecx,
4723 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
4724 Label megamorphic_pre;
4725 __ j(not_equal, &megamorphic_pre, Label::kFar);
4726 __ jmp(&done);
4727
4728 __ bind(&megamorphic_pre);
4729 __ jmp(&megamorphic, Label::kFar);
4730
4731 __ bind(&miss);
4698 // A monomorphic miss (i.e, here the cache is not uninitialized) goes 4732 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4699 // megamorphic. 4733 // megamorphic.
4700 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate))); 4734 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate)));
4701 __ j(equal, &initialize, Label::kNear); 4735 __ j(equal, &initialize, Label::kFar);
4702 // MegamorphicSentinel is an immortal immovable object (undefined) so no 4736 // MegamorphicSentinel is an immortal immovable object (undefined) so no
4703 // write-barrier is needed. 4737 // write-barrier is needed.
4738 __ bind(&megamorphic);
4739
4740 __ push(eax);
4741 __ push(ebx);
4742 __ push(ecx);
4743 __ push(edx);
4744 __ push(edi);
4745 __ push(esi);
4746
4747 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
4748 Label aligned, done_aligned;
4749 __ mov(esi, esp);
4750 __ test(esi, Immediate(kPointerSize));
4751 __ j(not_equal, &aligned, Label::kFar);
4752 __ push(Immediate(0));
4753 __ push(Immediate(4));
4754 __ mov(esi, Operand(esp, 8));
4755 __ jmp(&done_aligned, Label::kFar);
4756 __ bind(&aligned);
4757 __ push(Immediate(0));
4758 __ mov(esi, Operand(esp, 4));
4759 __ bind(&done_aligned);
4760
4704 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), 4761 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
4705 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); 4762 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
4706 __ jmp(&done, Label::kNear); 4763 __ jmp(&done, Label::kNear);
4707 4764
4708 // An uninitialized cache is patched with the function. 4765 // An uninitialized cache is patched with the function or sentinel to
4766 // indicate the ElementsKind if function is the Array constructor.
4709 __ bind(&initialize); 4767 __ bind(&initialize);
4768 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
4769 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset));
4770 // Make sure the function is the Array() function.
4771 __ cmp(edi, Operand(ecx,
4772 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
4773 __ j(not_equal, &not_array_function);
4774
4775 // The target function is the Array constructor, install a sentinel value in
4776 // the constructor's type info cell that will track the initial ElementsKind
4777 // that should be used for the array when its constructed.
4778 Handle<Object> initial_kind_sentinel =
4779 TypeFeedbackCells::MonomorphicArraySentinel(
4780 GetInitialFastElementsKind());
4781 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
4782 Immediate(initial_kind_sentinel));
4783 __ jmp(&done);
4784
4785 __ bind(&not_array_function);
4710 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi); 4786 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
4711 // No need for a write barrier here - cells are rescanned. 4787 // No need for a write barrier here - cells are rescanned.
4712 4788
4713 __ bind(&done); 4789 __ bind(&done);
4714 } 4790 }
4715 4791
4716 4792
4717 void CallFunctionStub::Generate(MacroAssembler* masm) { 4793 void CallFunctionStub::Generate(MacroAssembler* masm) {
4718 // ebx : cache cell for call target 4794 // ebx : cache cell for call target
4719 // edi : the function to call 4795 // edi : the function to call
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
4815 __ JumpIfSmi(edi, &non_function_call); 4891 __ JumpIfSmi(edi, &non_function_call);
4816 // Check that function is a JSFunction. 4892 // Check that function is a JSFunction.
4817 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4893 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4818 __ j(not_equal, &slow); 4894 __ j(not_equal, &slow);
4819 4895
4820 if (RecordCallTarget()) { 4896 if (RecordCallTarget()) {
4821 GenerateRecordCallTarget(masm); 4897 GenerateRecordCallTarget(masm);
4822 } 4898 }
4823 4899
4824 // Jump to the function-specific construct stub. 4900 // Jump to the function-specific construct stub.
4825 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 4901 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
4826 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); 4902 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
4827 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 4903 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
4828 __ jmp(ebx); 4904 __ jmp(ecx);
4829 4905
4830 // edi: called object 4906 // edi: called object
4831 // eax: number of arguments 4907 // eax: number of arguments
4832 // ecx: object map 4908 // ecx: object map
4833 Label do_call; 4909 Label do_call;
4834 __ bind(&slow); 4910 __ bind(&slow);
4835 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 4911 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
4836 __ j(not_equal, &non_function_call); 4912 __ j(not_equal, &non_function_call);
4837 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 4913 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
4838 __ jmp(&do_call); 4914 __ jmp(&do_call);
(...skipping 2688 matching lines...) Expand 10 before | Expand all | Expand 10 after
7527 // Restore ecx. 7603 // Restore ecx.
7528 __ pop(ecx); 7604 __ pop(ecx);
7529 __ ret(0); 7605 __ ret(0);
7530 } 7606 }
7531 7607
7532 #undef __ 7608 #undef __
7533 7609
7534 } } // namespace v8::internal 7610 } } // namespace v8::internal
7535 7611
7536 #endif // V8_TARGET_ARCH_IA32 7612 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698