OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 __ bind(&non_function_call); | 98 __ bind(&non_function_call); |
99 // Set expected number of arguments to zero (not changing eax). | 99 // Set expected number of arguments to zero (not changing eax). |
100 __ Set(ebx, Immediate(0)); | 100 __ Set(ebx, Immediate(0)); |
101 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 101 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
102 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), | 102 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), |
103 RelocInfo::CODE_TARGET); | 103 RelocInfo::CODE_TARGET); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 107 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
108 bool is_api_function) { | 108 bool is_api_function, |
| 109 bool count_constructions) { |
| 110 // Should never count constructions for api objects. |
| 111 ASSERT(!is_api_function || !count_constructions); |
| 112 |
109 // Enter a construct frame. | 113 // Enter a construct frame. |
110 __ EnterConstructFrame(); | 114 __ EnterConstructFrame(); |
111 | 115 |
112 // Store a smi-tagged arguments count on the stack. | 116 // Store a smi-tagged arguments count on the stack. |
113 __ SmiTag(eax); | 117 __ SmiTag(eax); |
114 __ push(eax); | 118 __ push(eax); |
115 | 119 |
116 // Push the function to invoke on the stack. | 120 // Push the function to invoke on the stack. |
117 __ push(edi); | 121 __ push(edi); |
118 | 122 |
(...skipping 22 matching lines...) Expand all Loading... |
141 __ j(not_equal, &rt_call); | 145 __ j(not_equal, &rt_call); |
142 | 146 |
143 // Check that the constructor is not constructing a JSFunction (see comments | 147 // Check that the constructor is not constructing a JSFunction (see comments |
144 // in Runtime_NewObject in runtime.cc). In which case the initial map's | 148 // in Runtime_NewObject in runtime.cc). In which case the initial map's |
145 // instance type would be JS_FUNCTION_TYPE. | 149 // instance type would be JS_FUNCTION_TYPE. |
146 // edi: constructor | 150 // edi: constructor |
147 // eax: initial map | 151 // eax: initial map |
148 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); | 152 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); |
149 __ j(equal, &rt_call); | 153 __ j(equal, &rt_call); |
150 | 154 |
| 155 if (count_constructions) { |
| 156 Label allocate; |
| 157 // Decrease generous allocation count. |
| 158 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 159 __ dec_b(FieldOperand(ecx, SharedFunctionInfo::kConstructionCountOffset)); |
| 160 __ j(not_zero, &allocate); |
| 161 |
| 162 __ push(eax); |
| 163 __ push(edi); |
| 164 |
| 165 __ push(edi); // constructor |
| 166 // The call will replace the stub, so the countdown is only done once. |
| 167 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 168 |
| 169 __ pop(edi); |
| 170 __ pop(eax); |
| 171 |
| 172 __ bind(&allocate); |
| 173 } |
| 174 |
151 // Now allocate the JSObject on the heap. | 175 // Now allocate the JSObject on the heap. |
152 // edi: constructor | 176 // edi: constructor |
153 // eax: initial map | 177 // eax: initial map |
154 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); | 178 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); |
155 __ shl(edi, kPointerSizeLog2); | 179 __ shl(edi, kPointerSizeLog2); |
156 __ AllocateInNewSpace(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 180 __ AllocateInNewSpace(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
157 // Allocated the JSObject, now initialize the fields. | 181 // Allocated the JSObject, now initialize the fields. |
158 // eax: initial map | 182 // eax: initial map |
159 // ebx: JSObject | 183 // ebx: JSObject |
160 // edi: start of next object | 184 // edi: start of next object |
161 __ mov(Operand(ebx, JSObject::kMapOffset), eax); | 185 __ mov(Operand(ebx, JSObject::kMapOffset), eax); |
162 __ mov(ecx, Factory::empty_fixed_array()); | 186 __ mov(ecx, Factory::empty_fixed_array()); |
163 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); | 187 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); |
164 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); | 188 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); |
165 // Set extra fields in the newly allocated object. | 189 // Set extra fields in the newly allocated object. |
166 // eax: initial map | 190 // eax: initial map |
167 // ebx: JSObject | 191 // ebx: JSObject |
168 // edi: start of next object | 192 // edi: start of next object |
169 { Label loop, entry; | 193 { Label loop, entry; |
170 __ mov(edx, Factory::undefined_value()); | 194 // To allow for truncation. |
| 195 if (count_constructions) { |
| 196 __ mov(edx, Factory::one_pointer_filler_map()); |
| 197 } else { |
| 198 __ mov(edx, Factory::undefined_value()); |
| 199 } |
171 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); | 200 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); |
172 __ jmp(&entry); | 201 __ jmp(&entry); |
173 __ bind(&loop); | 202 __ bind(&loop); |
174 __ mov(Operand(ecx, 0), edx); | 203 __ mov(Operand(ecx, 0), edx); |
175 __ add(Operand(ecx), Immediate(kPointerSize)); | 204 __ add(Operand(ecx), Immediate(kPointerSize)); |
176 __ bind(&entry); | 205 __ bind(&entry); |
177 __ cmp(ecx, Operand(edi)); | 206 __ cmp(ecx, Operand(edi)); |
178 __ j(less, &loop); | 207 __ j(less, &loop); |
179 } | 208 } |
180 | 209 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // Remove caller arguments from the stack and return. | 373 // Remove caller arguments from the stack and return. |
345 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 374 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
346 __ pop(ecx); | 375 __ pop(ecx); |
347 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 376 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
348 __ push(ecx); | 377 __ push(ecx); |
349 __ IncrementCounter(&Counters::constructed_objects, 1); | 378 __ IncrementCounter(&Counters::constructed_objects, 1); |
350 __ ret(0); | 379 __ ret(0); |
351 } | 380 } |
352 | 381 |
353 | 382 |
| 383 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
| 384 Generate_JSConstructStubHelper(masm, false, true); |
| 385 } |
| 386 |
| 387 |
354 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 388 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
355 Generate_JSConstructStubHelper(masm, false); | 389 Generate_JSConstructStubHelper(masm, false, false); |
356 } | 390 } |
357 | 391 |
358 | 392 |
359 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 393 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
360 Generate_JSConstructStubHelper(masm, true); | 394 Generate_JSConstructStubHelper(masm, true, false); |
361 } | 395 } |
362 | 396 |
363 | 397 |
364 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 398 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
365 bool is_construct) { | 399 bool is_construct) { |
366 // Clear the context before we push it when entering the JS frame. | 400 // Clear the context before we push it when entering the JS frame. |
367 __ xor_(esi, Operand(esi)); // clear esi | 401 __ xor_(esi, Operand(esi)); // clear esi |
368 | 402 |
369 // Enter an internal frame. | 403 // Enter an internal frame. |
370 __ EnterInternalFrame(); | 404 __ EnterInternalFrame(); |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 __ bind(&dont_adapt_arguments); | 1416 __ bind(&dont_adapt_arguments); |
1383 __ jmp(Operand(edx)); | 1417 __ jmp(Operand(edx)); |
1384 } | 1418 } |
1385 | 1419 |
1386 | 1420 |
1387 #undef __ | 1421 #undef __ |
1388 | 1422 |
1389 } } // namespace v8::internal | 1423 } } // namespace v8::internal |
1390 | 1424 |
1391 #endif // V8_TARGET_ARCH_IA32 | 1425 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |