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

Side by Side Diff: src/ia32/builtins-ia32.cc

Issue 283383006: Inobject slack tracking is done on a per-closure basis instead of per-shared info basis. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Bugfixes, improvements, cleanup Created 6 years, 7 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "v8.h" 5 #include "v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "codegen.h" 9 #include "codegen.h"
10 #include "deoptimizer.h" 10 #include "deoptimizer.h"
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode); 95 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode);
96 GenerateTailCallToReturnedCode(masm); 96 GenerateTailCallToReturnedCode(masm);
97 97
98 __ bind(&ok); 98 __ bind(&ok);
99 GenerateTailCallToSharedCode(masm); 99 GenerateTailCallToSharedCode(masm);
100 } 100 }
101 101
102 102
103 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 103 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
104 bool is_api_function, 104 bool is_api_function,
105 bool count_constructions,
106 bool create_memento) { 105 bool create_memento) {
107 // ----------- S t a t e ------------- 106 // ----------- S t a t e -------------
108 // -- eax: number of arguments 107 // -- eax: number of arguments
109 // -- edi: constructor function 108 // -- edi: constructor function
110 // -- ebx: allocation site or undefined 109 // -- ebx: allocation site or undefined
111 // ----------------------------------- 110 // -----------------------------------
112 111
113 // Should never count constructions for api objects.
114 ASSERT(!is_api_function || !count_constructions);
115
116 // Should never create mementos for api functions. 112 // Should never create mementos for api functions.
117 ASSERT(!is_api_function || !create_memento); 113 ASSERT(!is_api_function || !create_memento);
118 114
119 // Should never create mementos before slack tracking is finished.
120 ASSERT(!count_constructions || !create_memento);
121
122 // Enter a construct frame. 115 // Enter a construct frame.
123 { 116 {
124 FrameScope scope(masm, StackFrame::CONSTRUCT); 117 FrameScope scope(masm, StackFrame::CONSTRUCT);
125 118
126 if (create_memento) { 119 if (create_memento) {
127 __ AssertUndefinedOrAllocationSite(ebx); 120 __ AssertUndefinedOrAllocationSite(ebx);
128 __ push(ebx); 121 __ push(ebx);
129 } 122 }
130 123
131 // Store a smi-tagged arguments count on the stack. 124 // Store a smi-tagged arguments count on the stack.
(...skipping 25 matching lines...) Expand all
157 __ j(not_equal, &rt_call); 150 __ j(not_equal, &rt_call);
158 151
159 // Check that the constructor is not constructing a JSFunction (see 152 // Check that the constructor is not constructing a JSFunction (see
160 // comments in Runtime_NewObject in runtime.cc). In which case the 153 // comments in Runtime_NewObject in runtime.cc). In which case the
161 // initial map's instance type would be JS_FUNCTION_TYPE. 154 // initial map's instance type would be JS_FUNCTION_TYPE.
162 // edi: constructor 155 // edi: constructor
163 // eax: initial map 156 // eax: initial map
164 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 157 __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
165 __ j(equal, &rt_call); 158 __ j(equal, &rt_call);
166 159
167 if (count_constructions) { 160 if (!is_api_function) {
161 // esi: slack tracking counter
Michael Starzinger 2014/05/21 10:42:01 nit: At this point esi does not yet contain the co
Igor Sheludko 2014/05/22 08:05:42 Done.
168 Label allocate; 162 Label allocate;
163 // The code below relies on these assumptions.
164 STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
165 STATIC_ASSERT(Map::ConstructionCount::kShift +
166 Map::ConstructionCount::kSize == 32);
167 // Check if slack tracking is enabled.
168 __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
169 __ shr(esi, Map::ConstructionCount::kShift);
170 __ j(zero, &allocate); // JSFunction::kNoSlackTracking
169 // Decrease generous allocation count. 171 // Decrease generous allocation count.
170 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 172 __ sub(FieldOperand(eax, Map::kBitField3Offset),
171 __ dec_b(FieldOperand(ecx, 173 Immediate(1 << Map::ConstructionCount::kShift));
172 SharedFunctionInfo::kConstructionCountOffset)); 174
173 __ j(not_zero, &allocate); 175 __ cmp(esi, JSFunction::kFinishSlackTracking);
176 __ j(not_equal, &allocate);
174 177
175 __ push(eax); 178 __ push(eax);
176 __ push(edi); 179 __ push(edi);
177 180
178 __ push(edi); // constructor 181 __ push(edi); // constructor
179 // The call will replace the stub, so the countdown is only done once.
180 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 182 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
181 183
182 __ pop(edi); 184 __ pop(edi);
183 __ pop(eax); 185 __ pop(eax);
186 __ xor_(esi, esi); // JSFunction::kNoSlackTracking
184 187
185 __ bind(&allocate); 188 __ bind(&allocate);
186 } 189 }
187 190
188 // Now allocate the JSObject on the heap. 191 // Now allocate the JSObject on the heap.
189 // edi: constructor 192 // edi: constructor
190 // eax: initial map 193 // eax: initial map
191 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 194 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
192 __ shl(edi, kPointerSizeLog2); 195 __ shl(edi, kPointerSizeLog2);
193 if (create_memento) { 196 if (create_memento) {
194 __ add(edi, Immediate(AllocationMemento::kSize)); 197 __ add(edi, Immediate(AllocationMemento::kSize));
195 } 198 }
196 199
197 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 200 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
198 201
199 Factory* factory = masm->isolate()->factory(); 202 Factory* factory = masm->isolate()->factory();
200 203
201 // Allocated the JSObject, now initialize the fields. 204 // Allocated the JSObject, now initialize the fields.
202 // eax: initial map 205 // eax: initial map
203 // ebx: JSObject 206 // ebx: JSObject
204 // edi: start of next object (including memento if create_memento) 207 // edi: start of next object (including memento if create_memento)
205 __ mov(Operand(ebx, JSObject::kMapOffset), eax); 208 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
206 __ mov(ecx, factory->empty_fixed_array()); 209 __ mov(ecx, factory->empty_fixed_array());
207 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 210 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
208 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 211 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
209 // Set extra fields in the newly allocated object. 212 // Set extra fields in the newly allocated object.
210 // eax: initial map 213 // eax: initial map
211 // ebx: JSObject 214 // ebx: JSObject
212 // edi: start of next object (including memento if create_memento) 215 // edi: start of next object (including memento if create_memento)
216 // esi: slack tracking counter (non-API function case)
217 __ mov(edx, factory->undefined_value());
213 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 218 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
214 __ mov(edx, factory->undefined_value()); 219 if (is_api_function) {
215 if (count_constructions) { 220 __ InitializeFieldsWithFiller(ecx, edi, edx);
221 } else {
222 Label no_inobject_slack_tracking, done_field_initialization;
223
224 // Check if slack tracking is enabled.
225 __ cmp(esi, JSFunction::kNoSlackTracking);
226 __ j(equal, &no_inobject_slack_tracking);
227
228 // Allocate object with a slack.
216 __ movzx_b(esi, 229 __ movzx_b(esi,
217 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 230 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
218 __ lea(esi, 231 __ lea(esi,
219 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 232 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
220 // esi: offset of first field after pre-allocated fields 233 // esi: offset of first field after pre-allocated fields
221 if (FLAG_debug_code) { 234 if (FLAG_debug_code) {
222 __ cmp(esi, edi); 235 __ cmp(esi, edi);
223 __ Assert(less_equal, 236 __ Assert(less_equal,
224 kUnexpectedNumberOfPreAllocatedPropertyFields); 237 kUnexpectedNumberOfPreAllocatedPropertyFields);
225 } 238 }
226 __ InitializeFieldsWithFiller(ecx, esi, edx); 239 __ InitializeFieldsWithFiller(ecx, esi, edx);
227 __ mov(edx, factory->one_pointer_filler_map()); 240 __ mov(edx, factory->one_pointer_filler_map());
228 __ InitializeFieldsWithFiller(ecx, edi, edx); 241 __ InitializeFieldsWithFiller(ecx, edi, edx);
229 } else if (create_memento) { 242 __ jmp(&done_field_initialization);
Michael Starzinger 2014/05/21 10:42:01 This will skip initialization of the memento even
Igor Sheludko 2014/05/22 08:05:42 Done. Now mementos are always initialized if they
230 __ lea(esi, Operand(edi, -AllocationMemento::kSize));
231 __ InitializeFieldsWithFiller(ecx, esi, edx);
232 243
233 // Fill in memento fields if necessary. 244 __ bind(&no_inobject_slack_tracking);
234 // esi: points to the allocated but uninitialized memento. 245
235 Handle<Map> allocation_memento_map = factory->allocation_memento_map(); 246 if (create_memento) {
236 __ mov(Operand(esi, AllocationMemento::kMapOffset), 247 __ lea(esi, Operand(edi, -AllocationMemento::kSize));
237 allocation_memento_map); 248 __ InitializeFieldsWithFiller(ecx, esi, edx);
238 // Get the cell or undefined. 249
239 __ mov(edx, Operand(esp, kPointerSize*2)); 250 // Fill in memento fields if necessary.
240 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), 251 // esi: points to the allocated but uninitialized memento.
241 edx); 252 __ mov(Operand(esi, AllocationMemento::kMapOffset),
242 } else { 253 factory->allocation_memento_map());
243 __ InitializeFieldsWithFiller(ecx, edi, edx); 254 // Get the cell or undefined.
255 __ mov(edx, Operand(esp, kPointerSize*2));
256 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset),
257 edx);
258 } else {
259 __ InitializeFieldsWithFiller(ecx, edi, edx);
260 }
261 __ bind(&done_field_initialization);
244 } 262 }
245 263
246 // Add the object tag to make the JSObject real, so that we can continue 264 // Add the object tag to make the JSObject real, so that we can continue
247 // and jump into the continuation code at any time from now on. Any 265 // and jump into the continuation code at any time from now on. Any
248 // failures need to undo the allocation, so that the heap is in a 266 // failures need to undo the allocation, so that the heap is in a
249 // consistent state and verifiable. 267 // consistent state and verifiable.
250 // eax: initial map 268 // eax: initial map
251 // ebx: JSObject 269 // ebx: JSObject
252 // edi: start of next object 270 // edi: start of next object
253 __ or_(ebx, Immediate(kHeapObjectTag)); 271 __ or_(ebx, Immediate(kHeapObjectTag));
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 Handle<Code> code = 424 Handle<Code> code =
407 masm->isolate()->builtins()->HandleApiCallConstruct(); 425 masm->isolate()->builtins()->HandleApiCallConstruct();
408 __ call(code, RelocInfo::CODE_TARGET); 426 __ call(code, RelocInfo::CODE_TARGET);
409 } else { 427 } else {
410 ParameterCount actual(eax); 428 ParameterCount actual(eax);
411 __ InvokeFunction(edi, actual, CALL_FUNCTION, 429 __ InvokeFunction(edi, actual, CALL_FUNCTION,
412 NullCallWrapper()); 430 NullCallWrapper());
413 } 431 }
414 432
415 // Store offset of return address for deoptimizer. 433 // Store offset of return address for deoptimizer.
416 if (!is_api_function && !count_constructions) { 434 if (!is_api_function) {
417 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 435 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
418 } 436 }
419 437
420 // Restore context from the frame. 438 // Restore context from the frame.
421 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 439 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
422 440
423 // If the result is an object (in the ECMA sense), we should get rid 441 // If the result is an object (in the ECMA sense), we should get rid
424 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 442 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
425 // on page 74. 443 // on page 74.
426 Label use_receiver, exit; 444 Label use_receiver, exit;
(...skipping 21 matching lines...) Expand all
448 // Remove caller arguments from the stack and return. 466 // Remove caller arguments from the stack and return.
449 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 467 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
450 __ pop(ecx); 468 __ pop(ecx);
451 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 469 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
452 __ push(ecx); 470 __ push(ecx);
453 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 471 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
454 __ ret(0); 472 __ ret(0);
455 } 473 }
456 474
457 475
458 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
459 Generate_JSConstructStubHelper(masm, false, true, false);
460 }
461
462
463 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 476 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
464 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); 477 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
465 } 478 }
466 479
467 480
468 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 481 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
469 Generate_JSConstructStubHelper(masm, true, false, false); 482 Generate_JSConstructStubHelper(masm, true, false);
470 } 483 }
471 484
472 485
473 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 486 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
474 bool is_construct) { 487 bool is_construct) {
475 ProfileEntryHookStub::MaybeCallEntryHook(masm); 488 ProfileEntryHookStub::MaybeCallEntryHook(masm);
476 489
477 // Clear the context before we push it when entering the internal frame. 490 // Clear the context before we push it when entering the internal frame.
478 __ Move(esi, Immediate(0)); 491 __ Move(esi, Immediate(0));
479 492
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 1447
1435 __ bind(&ok); 1448 __ bind(&ok);
1436 __ ret(0); 1449 __ ret(0);
1437 } 1450 }
1438 1451
1439 #undef __ 1452 #undef __
1440 } 1453 }
1441 } // namespace v8::internal 1454 } // namespace v8::internal
1442 1455
1443 #endif // V8_TARGET_ARCH_IA32 1456 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/mark-compact.h » ('j') | src/objects.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698