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

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

Issue 292183008: Reland r21442 "Inobject slack tracking is done on a per-closure basis instead of per-shared info ba… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: The fix 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
« no previous file with comments | « src/hydrogen.cc ('k') | src/mark-compact.h » ('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 // 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) {
168 Label allocate; 161 Label allocate;
162 // The code below relies on these assumptions.
163 STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
164 STATIC_ASSERT(Map::ConstructionCount::kShift +
165 Map::ConstructionCount::kSize == 32);
166 // Check if slack tracking is enabled.
167 __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
168 __ shr(esi, Map::ConstructionCount::kShift);
169 __ j(zero, &allocate); // JSFunction::kNoSlackTracking
169 // Decrease generous allocation count. 170 // Decrease generous allocation count.
170 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 171 __ sub(FieldOperand(eax, Map::kBitField3Offset),
171 __ dec_b(FieldOperand(ecx, 172 Immediate(1 << Map::ConstructionCount::kShift));
172 SharedFunctionInfo::kConstructionCountOffset)); 173
173 __ j(not_zero, &allocate); 174 __ cmp(esi, JSFunction::kFinishSlackTracking);
175 __ j(not_equal, &allocate);
174 176
175 __ push(eax); 177 __ push(eax);
176 __ push(edi); 178 __ push(edi);
177 179
178 __ push(edi); // constructor 180 __ push(edi); // constructor
179 // The call will replace the stub, so the countdown is only done once.
180 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 181 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
181 182
182 __ pop(edi); 183 __ pop(edi);
183 __ pop(eax); 184 __ pop(eax);
185 __ xor_(esi, esi); // JSFunction::kNoSlackTracking
184 186
185 __ bind(&allocate); 187 __ bind(&allocate);
186 } 188 }
187 189
188 // Now allocate the JSObject on the heap. 190 // Now allocate the JSObject on the heap.
189 // edi: constructor 191 // edi: constructor
190 // eax: initial map 192 // eax: initial map
191 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 193 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
192 __ shl(edi, kPointerSizeLog2); 194 __ shl(edi, kPointerSizeLog2);
193 if (create_memento) { 195 if (create_memento) {
194 __ add(edi, Immediate(AllocationMemento::kSize)); 196 __ add(edi, Immediate(AllocationMemento::kSize));
195 } 197 }
196 198
197 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 199 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
198 200
199 Factory* factory = masm->isolate()->factory(); 201 Factory* factory = masm->isolate()->factory();
200 202
201 // Allocated the JSObject, now initialize the fields. 203 // Allocated the JSObject, now initialize the fields.
202 // eax: initial map 204 // eax: initial map
203 // ebx: JSObject 205 // ebx: JSObject
204 // edi: start of next object (including memento if create_memento) 206 // edi: start of next object (including memento if create_memento)
205 __ mov(Operand(ebx, JSObject::kMapOffset), eax); 207 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
206 __ mov(ecx, factory->empty_fixed_array()); 208 __ mov(ecx, factory->empty_fixed_array());
207 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 209 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
208 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 210 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
209 // Set extra fields in the newly allocated object. 211 // Set extra fields in the newly allocated object.
210 // eax: initial map 212 // eax: initial map
211 // ebx: JSObject 213 // ebx: JSObject
212 // edi: start of next object (including memento if create_memento) 214 // edi: start of next object (including memento if create_memento)
215 // esi: slack tracking counter (non-API function case)
216 __ mov(edx, factory->undefined_value());
213 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 217 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
214 __ mov(edx, factory->undefined_value()); 218 if (!is_api_function) {
215 if (count_constructions) { 219 Label no_inobject_slack_tracking;
220
221 // Check if slack tracking is enabled.
222 __ cmp(esi, JSFunction::kNoSlackTracking);
223 __ j(equal, &no_inobject_slack_tracking);
224
225 // Allocate object with a slack.
216 __ movzx_b(esi, 226 __ movzx_b(esi,
217 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 227 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
218 __ lea(esi, 228 __ lea(esi,
219 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 229 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
220 // esi: offset of first field after pre-allocated fields 230 // esi: offset of first field after pre-allocated fields
221 if (FLAG_debug_code) { 231 if (FLAG_debug_code) {
222 __ cmp(esi, edi); 232 __ cmp(esi, edi);
223 __ Assert(less_equal, 233 __ Assert(less_equal,
224 kUnexpectedNumberOfPreAllocatedPropertyFields); 234 kUnexpectedNumberOfPreAllocatedPropertyFields);
225 } 235 }
226 __ InitializeFieldsWithFiller(ecx, esi, edx); 236 __ InitializeFieldsWithFiller(ecx, esi, edx);
227 __ mov(edx, factory->one_pointer_filler_map()); 237 __ mov(edx, factory->one_pointer_filler_map());
228 __ InitializeFieldsWithFiller(ecx, edi, edx); 238 // Fill the remaining fields with one pointer filler map.
229 } else if (create_memento) { 239
240 __ bind(&no_inobject_slack_tracking);
241 }
242
243 if (create_memento) {
230 __ lea(esi, Operand(edi, -AllocationMemento::kSize)); 244 __ lea(esi, Operand(edi, -AllocationMemento::kSize));
231 __ InitializeFieldsWithFiller(ecx, esi, edx); 245 __ InitializeFieldsWithFiller(ecx, esi, edx);
232 246
233 // Fill in memento fields if necessary. 247 // Fill in memento fields if necessary.
234 // esi: points to the allocated but uninitialized memento. 248 // esi: points to the allocated but uninitialized memento.
235 Handle<Map> allocation_memento_map = factory->allocation_memento_map();
236 __ mov(Operand(esi, AllocationMemento::kMapOffset), 249 __ mov(Operand(esi, AllocationMemento::kMapOffset),
237 allocation_memento_map); 250 factory->allocation_memento_map());
238 // Get the cell or undefined. 251 // Get the cell or undefined.
239 __ mov(edx, Operand(esp, kPointerSize*2)); 252 __ mov(edx, Operand(esp, kPointerSize*2));
240 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), 253 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset),
241 edx); 254 edx);
242 } else { 255 } else {
243 __ InitializeFieldsWithFiller(ecx, edi, edx); 256 __ InitializeFieldsWithFiller(ecx, edi, edx);
244 } 257 }
245 258
246 // Add the object tag to make the JSObject real, so that we can continue 259 // 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 260 // and jump into the continuation code at any time from now on. Any
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 // Allocate the new receiver object using the runtime call. 346 // Allocate the new receiver object using the runtime call.
334 __ bind(&rt_call); 347 __ bind(&rt_call);
335 int offset = 0; 348 int offset = 0;
336 if (create_memento) { 349 if (create_memento) {
337 // Get the cell or allocation site. 350 // Get the cell or allocation site.
338 __ mov(edi, Operand(esp, kPointerSize * 2)); 351 __ mov(edi, Operand(esp, kPointerSize * 2));
339 __ push(edi); 352 __ push(edi);
340 offset = kPointerSize; 353 offset = kPointerSize;
341 } 354 }
342 355
343 // Must restore edi (constructor) before calling runtime. 356 // Must restore esi (context) and edi (constructor) before calling runtime.
357 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
344 __ mov(edi, Operand(esp, offset)); 358 __ mov(edi, Operand(esp, offset));
345 // edi: function (constructor) 359 // edi: function (constructor)
346 __ push(edi); 360 __ push(edi);
347 if (create_memento) { 361 if (create_memento) {
348 __ CallRuntime(Runtime::kHiddenNewObjectWithAllocationSite, 2); 362 __ CallRuntime(Runtime::kHiddenNewObjectWithAllocationSite, 2);
349 } else { 363 } else {
350 __ CallRuntime(Runtime::kHiddenNewObject, 1); 364 __ CallRuntime(Runtime::kHiddenNewObject, 1);
351 } 365 }
352 __ mov(ebx, eax); // store result in ebx 366 __ mov(ebx, eax); // store result in ebx
353 367
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 Handle<Code> code = 420 Handle<Code> code =
407 masm->isolate()->builtins()->HandleApiCallConstruct(); 421 masm->isolate()->builtins()->HandleApiCallConstruct();
408 __ call(code, RelocInfo::CODE_TARGET); 422 __ call(code, RelocInfo::CODE_TARGET);
409 } else { 423 } else {
410 ParameterCount actual(eax); 424 ParameterCount actual(eax);
411 __ InvokeFunction(edi, actual, CALL_FUNCTION, 425 __ InvokeFunction(edi, actual, CALL_FUNCTION,
412 NullCallWrapper()); 426 NullCallWrapper());
413 } 427 }
414 428
415 // Store offset of return address for deoptimizer. 429 // Store offset of return address for deoptimizer.
416 if (!is_api_function && !count_constructions) { 430 if (!is_api_function) {
417 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 431 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
418 } 432 }
419 433
420 // Restore context from the frame. 434 // Restore context from the frame.
421 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 435 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
422 436
423 // If the result is an object (in the ECMA sense), we should get rid 437 // 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 438 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
425 // on page 74. 439 // on page 74.
426 Label use_receiver, exit; 440 Label use_receiver, exit;
(...skipping 21 matching lines...) Expand all
448 // Remove caller arguments from the stack and return. 462 // Remove caller arguments from the stack and return.
449 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 463 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
450 __ pop(ecx); 464 __ pop(ecx);
451 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 465 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
452 __ push(ecx); 466 __ push(ecx);
453 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 467 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
454 __ ret(0); 468 __ ret(0);
455 } 469 }
456 470
457 471
458 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
459 Generate_JSConstructStubHelper(masm, false, true, false);
460 }
461
462
463 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 472 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
464 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); 473 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
465 } 474 }
466 475
467 476
468 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 477 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
469 Generate_JSConstructStubHelper(masm, true, false, false); 478 Generate_JSConstructStubHelper(masm, true, false);
470 } 479 }
471 480
472 481
473 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 482 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
474 bool is_construct) { 483 bool is_construct) {
475 ProfileEntryHookStub::MaybeCallEntryHook(masm); 484 ProfileEntryHookStub::MaybeCallEntryHook(masm);
476 485
477 // Clear the context before we push it when entering the internal frame. 486 // Clear the context before we push it when entering the internal frame.
478 __ Move(esi, Immediate(0)); 487 __ Move(esi, Immediate(0));
479 488
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 1443
1435 __ bind(&ok); 1444 __ bind(&ok);
1436 __ ret(0); 1445 __ ret(0);
1437 } 1446 }
1438 1447
1439 #undef __ 1448 #undef __
1440 } 1449 }
1441 } // namespace v8::internal 1450 } // namespace v8::internal
1442 1451
1443 #endif // V8_TARGET_ARCH_IA32 1452 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/mark-compact.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698