OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 if (FLAG_print_scopes && FLAG_print_ast) { | 203 if (FLAG_print_scopes && FLAG_print_ast) { |
204 // Print the function scope before code generation. | 204 // Print the function scope before code generation. |
205 AstPrinter::PrintFunctionScope(parsed_function_); | 205 AstPrinter::PrintFunctionScope(parsed_function_); |
206 } | 206 } |
207 if (FLAG_print_ast) { | 207 if (FLAG_print_ast) { |
208 // Print the function ast before code generation. | 208 // Print the function ast before code generation. |
209 AstPrinter::PrintFunctionNodes(parsed_function_); | 209 AstPrinter::PrintFunctionNodes(parsed_function_); |
210 } | 210 } |
211 if (FLAG_trace_functions) { | 211 if (FLAG_trace_functions) { |
212 // Preserve ECX (ic-data array or object) and EDX (arguments descriptor). | 212 // Preserve ECX (ic-data array or object) and EDX (arguments descriptor). |
| 213 __ nop(2); // Make sure the code is patchable. |
213 __ pushl(ECX); | 214 __ pushl(ECX); |
214 __ pushl(EDX); | 215 __ pushl(EDX); |
215 const Function& function = | 216 const Function& function = |
216 Function::ZoneHandle(parsed_function_.function().raw()); | 217 Function::ZoneHandle(parsed_function_.function().raw()); |
217 __ LoadObject(EAX, function); | 218 __ LoadObject(EAX, function); |
218 __ pushl(EAX); | 219 __ pushl(EAX); |
219 GenerateCallRuntime(AstNode::kNoId, | 220 GenerateCallRuntime(AstNode::kNoId, |
220 0, | 221 0, |
221 kTraceFunctionEntryRuntimeEntry); | 222 kTraceFunctionEntryRuntimeEntry); |
222 __ popl(EAX); | 223 __ popl(EAX); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 265 |
265 // Pre entry code is called before the frame has been constructed: | 266 // Pre entry code is called before the frame has been constructed: |
266 // - check for stack overflow. | 267 // - check for stack overflow. |
267 // - optionally count function invocations. | 268 // - optionally count function invocations. |
268 // - optionally trigger optimizing compiler if invocation threshold has been | 269 // - optionally trigger optimizing compiler if invocation threshold has been |
269 // reached. | 270 // reached. |
270 // Note that first 5 bytes may be patched with a jump. | 271 // Note that first 5 bytes may be patched with a jump. |
271 // TODO(srdjan): Add check that no object is inlined in the first | 272 // TODO(srdjan): Add check that no object is inlined in the first |
272 // 5 bytes (length of a jump instruction). | 273 // 5 bytes (length of a jump instruction). |
273 void CodeGenerator::GeneratePreEntryCode() { | 274 void CodeGenerator::GeneratePreEntryCode() { |
274 // Stack overflow check. | |
275 __ cmpl(ESP, | |
276 Address::Absolute(Isolate::Current()->stack_limit_address())); | |
277 __ j(BELOW_EQUAL, &StubCode::StackOverflowLabel()); | |
278 // Do not optimize if: | 275 // Do not optimize if: |
279 // - we count invocations. | 276 // - we count invocations. |
280 // - optimization disabled via negative 'optimization_invocation_threshold; | 277 // - optimization disabled via negative 'optimization_invocation_threshold; |
281 // - function is marked as non-optimizable. | 278 // - function is marked as non-optimizable. |
282 // - type checks are enabled. | 279 // - type checks are enabled. |
283 const bool may_optimize = | 280 const bool may_optimize = |
284 !FLAG_report_invocation_count && | 281 !FLAG_report_invocation_count && |
285 (FLAG_optimization_invocation_threshold >= 0) && | 282 (FLAG_optimization_invocation_threshold >= 0) && |
286 !Isolate::Current()->debugger()->IsActive() && | 283 !Isolate::Current()->debugger()->IsActive() && |
287 parsed_function_.function().is_optimizable(); | 284 parsed_function_.function().is_optimizable(); |
288 // Count invocation and check. | 285 // Count invocation and check. |
289 if (FLAG_report_invocation_count || may_optimize) { | 286 if (FLAG_report_invocation_count || may_optimize) { |
| 287 // TODO(turnidge): It would be nice to remove this nop. Right now |
| 288 // we need it to make sure the function is still patchable. |
| 289 __ nop(5); |
290 const Function& function = | 290 const Function& function = |
291 Function::ZoneHandle(parsed_function_.function().raw()); | 291 Function::ZoneHandle(parsed_function_.function().raw()); |
292 __ LoadObject(EAX, function); | 292 __ LoadObject(EAX, function); |
293 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset())); | 293 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset())); |
294 __ incl(EBX); | 294 __ incl(EBX); |
295 if (may_optimize) { | 295 if (may_optimize) { |
296 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold)); | 296 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold)); |
297 __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel()); | 297 __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel()); |
298 } | 298 } |
299 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX); | 299 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX); |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 // Initialize locals. | 719 // Initialize locals. |
720 // TODO(regis): For now, always unroll the init loop. Decide later above | 720 // TODO(regis): For now, always unroll the init loop. Decide later above |
721 // which threshold to implement a loop. | 721 // which threshold to implement a loop. |
722 // Consider emitting pushes instead of moves. | 722 // Consider emitting pushes instead of moves. |
723 for (int index = first_local_index; index > first_free_frame_index; index--) { | 723 for (int index = first_local_index; index > first_free_frame_index; index--) { |
724 if (index == first_local_index) { | 724 if (index == first_local_index) { |
725 __ movl(EAX, raw_null); | 725 __ movl(EAX, raw_null); |
726 } | 726 } |
727 __ movl(Address(EBP, index * kWordSize), EAX); | 727 __ movl(Address(EBP, index * kWordSize), EAX); |
728 } | 728 } |
| 729 |
| 730 // Generate stack overflow check. |
| 731 __ cmpl(ESP, |
| 732 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 733 Label no_stack_overflow; |
| 734 __ j(ABOVE, &no_stack_overflow); |
| 735 GenerateCallRuntime(AstNode::kNoId, |
| 736 function.token_index(), |
| 737 kStackOverflowRuntimeEntry); |
| 738 __ Bind(&no_stack_overflow); |
729 } | 739 } |
730 | 740 |
731 | 741 |
732 void CodeGenerator::GenerateReturnEpilog() { | 742 void CodeGenerator::GenerateReturnEpilog() { |
733 // Unchain the context(s) up to context level 0. | 743 // Unchain the context(s) up to context level 0. |
734 int context_level = state()->context_level(); | 744 int context_level = state()->context_level(); |
735 ASSERT(context_level >= 0); | 745 ASSERT(context_level >= 0); |
736 while (context_level-- > 0) { | 746 while (context_level-- > 0) { |
737 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 747 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
738 } | 748 } |
(...skipping 2033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2772 message_buffer, kMessageBufferSize, | 2782 message_buffer, kMessageBufferSize, |
2773 format, args); | 2783 format, args); |
2774 va_end(args); | 2784 va_end(args); |
2775 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 2785 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
2776 UNREACHABLE(); | 2786 UNREACHABLE(); |
2777 } | 2787 } |
2778 | 2788 |
2779 } // namespace dart | 2789 } // namespace dart |
2780 | 2790 |
2781 #endif // defined TARGET_ARCH_IA32 | 2791 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |