OLD | NEW |
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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 Comment cmnt(masm_, "[ Stack check"); | 335 Comment cmnt(masm_, "[ Stack check"); |
336 Label ok; | 336 Label ok; |
337 | 337 |
338 if (FLAG_count_based_interrupts) { | 338 if (FLAG_count_based_interrupts) { |
339 int weight = 1; | 339 int weight = 1; |
340 if (FLAG_weighted_back_edges) { | 340 if (FLAG_weighted_back_edges) { |
341 ASSERT(back_edge_target->is_bound()); | 341 ASSERT(back_edge_target->is_bound()); |
342 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 342 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
343 weight = Min(127, Max(1, distance / 100)); | 343 weight = Min(127, Max(1, distance / 100)); |
344 } | 344 } |
345 __ sub(Operand::Cell(profiling_counter_), Immediate(Smi::FromInt(weight))); | 345 if (Serializer::enabled()) { |
| 346 __ mov(ebx, Immediate(profiling_counter_)); |
| 347 __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| 348 Immediate(Smi::FromInt(weight))); |
| 349 } else { |
| 350 // This version is slightly faster, but not snapshot safe. |
| 351 __ sub(Operand::Cell(profiling_counter_), |
| 352 Immediate(Smi::FromInt(weight))); |
| 353 } |
346 __ j(positive, &ok, Label::kNear); | 354 __ j(positive, &ok, Label::kNear); |
347 InterruptStub stub; | 355 InterruptStub stub; |
348 __ CallStub(&stub); | 356 __ CallStub(&stub); |
349 } else { | 357 } else { |
350 // Count based interrupts happen often enough when they are enabled | 358 // Count based interrupts happen often enough when they are enabled |
351 // that the additional stack checks are not necessary (they would | 359 // that the additional stack checks are not necessary (they would |
352 // only check for interrupts). | 360 // only check for interrupts). |
353 ExternalReference stack_limit = | 361 ExternalReference stack_limit = |
354 ExternalReference::address_of_stack_limit(isolate()); | 362 ExternalReference::address_of_stack_limit(isolate()); |
355 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 363 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
356 __ j(above_equal, &ok, Label::kNear); | 364 __ j(above_equal, &ok, Label::kNear); |
357 StackCheckStub stub; | 365 StackCheckStub stub; |
358 __ CallStub(&stub); | 366 __ CallStub(&stub); |
359 } | 367 } |
360 | 368 |
361 // Record a mapping of this PC offset to the OSR id. This is used to find | 369 // Record a mapping of this PC offset to the OSR id. This is used to find |
362 // the AST id from the unoptimized code in order to use it as a key into | 370 // the AST id from the unoptimized code in order to use it as a key into |
363 // the deoptimization input data found in the optimized code. | 371 // the deoptimization input data found in the optimized code. |
364 RecordStackCheck(stmt->OsrEntryId()); | 372 RecordStackCheck(stmt->OsrEntryId()); |
365 | 373 |
366 // Loop stack checks can be patched to perform on-stack replacement. In | 374 // Loop stack checks can be patched to perform on-stack replacement. In |
367 // order to decide whether or not to perform OSR we embed the loop depth | 375 // order to decide whether or not to perform OSR we embed the loop depth |
368 // in a test instruction after the call so we can extract it from the OSR | 376 // in a test instruction after the call so we can extract it from the OSR |
369 // builtin. | 377 // builtin. |
370 ASSERT(loop_depth() > 0); | 378 ASSERT(loop_depth() > 0); |
371 __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker))); | 379 __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker))); |
372 | 380 |
373 if (FLAG_count_based_interrupts) { | 381 if (FLAG_count_based_interrupts) { |
374 // Reset the countdown. | 382 // Reset the countdown. |
375 __ mov(Operand::Cell(profiling_counter_), | 383 if (Serializer::enabled()) { |
376 Immediate(Smi::FromInt(FLAG_interrupt_budget))); | 384 __ mov(ebx, Immediate(profiling_counter_)); |
| 385 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| 386 Immediate(Smi::FromInt(FLAG_interrupt_budget))); |
| 387 } else { |
| 388 __ mov(Operand::Cell(profiling_counter_), |
| 389 Immediate(Smi::FromInt(FLAG_interrupt_budget))); |
| 390 } |
377 } | 391 } |
378 | 392 |
379 __ bind(&ok); | 393 __ bind(&ok); |
380 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 394 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
381 // Record a mapping of the OSR id to this PC. This is used if the OSR | 395 // Record a mapping of the OSR id to this PC. This is used if the OSR |
382 // entry becomes the target of a bailout. We don't expect it to be, but | 396 // entry becomes the target of a bailout. We don't expect it to be, but |
383 // we want it to work if it is. | 397 // we want it to work if it is. |
384 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); | 398 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
385 } | 399 } |
386 | 400 |
387 | 401 |
388 void FullCodeGenerator::EmitReturnSequence() { | 402 void FullCodeGenerator::EmitReturnSequence() { |
389 Comment cmnt(masm_, "[ Return sequence"); | 403 Comment cmnt(masm_, "[ Return sequence"); |
390 if (return_label_.is_bound()) { | 404 if (return_label_.is_bound()) { |
391 __ jmp(&return_label_); | 405 __ jmp(&return_label_); |
392 } else { | 406 } else { |
393 // Common return label | 407 // Common return label |
394 __ bind(&return_label_); | 408 __ bind(&return_label_); |
395 if (FLAG_trace) { | 409 if (FLAG_trace) { |
396 __ push(eax); | 410 __ push(eax); |
397 __ CallRuntime(Runtime::kTraceExit, 1); | 411 __ CallRuntime(Runtime::kTraceExit, 1); |
398 } | 412 } |
399 if (FLAG_interrupt_at_exit) { | 413 if (FLAG_interrupt_at_exit) { |
400 // Pretend that the exit is a backwards jump to the entry. | 414 // Pretend that the exit is a backwards jump to the entry. |
401 int weight = 1; | 415 int weight = 1; |
402 if (FLAG_weighted_back_edges) { | 416 if (FLAG_weighted_back_edges) { |
403 int distance = masm_->pc_offset(); | 417 int distance = masm_->pc_offset(); |
404 weight = Min(127, Max(1, distance / 100)); | 418 weight = Min(127, Max(1, distance / 100)); |
405 } | 419 } |
406 __ sub(Operand::Cell(profiling_counter_), | 420 if (Serializer::enabled()) { |
407 Immediate(Smi::FromInt(weight))); | 421 __ mov(ebx, Immediate(profiling_counter_)); |
| 422 __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| 423 Immediate(Smi::FromInt(weight))); |
| 424 } else { |
| 425 // This version is slightly faster, but not snapshot safe. |
| 426 __ sub(Operand::Cell(profiling_counter_), |
| 427 Immediate(Smi::FromInt(weight))); |
| 428 } |
408 Label ok; | 429 Label ok; |
409 __ j(positive, &ok, Label::kNear); | 430 __ j(positive, &ok, Label::kNear); |
410 __ push(eax); | 431 __ push(eax); |
411 InterruptStub stub; | 432 InterruptStub stub; |
412 __ CallStub(&stub); | 433 __ CallStub(&stub); |
413 __ pop(eax); | 434 __ pop(eax); |
414 // Reset the countdown. | 435 // Reset the countdown. |
415 __ mov(Operand::Cell(profiling_counter_), | 436 if (Serializer::enabled()) { |
416 Immediate(Smi::FromInt(FLAG_interrupt_budget))); | 437 __ mov(ebx, Immediate(profiling_counter_)); |
| 438 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| 439 Immediate(Smi::FromInt(FLAG_interrupt_budget))); |
| 440 } else { |
| 441 __ mov(Operand::Cell(profiling_counter_), |
| 442 Immediate(Smi::FromInt(FLAG_interrupt_budget))); |
| 443 } |
417 __ bind(&ok); | 444 __ bind(&ok); |
418 } | 445 } |
419 #ifdef DEBUG | 446 #ifdef DEBUG |
420 // Add a label for checking the size of the code used for returning. | 447 // Add a label for checking the size of the code used for returning. |
421 Label check_exit_codesize; | 448 Label check_exit_codesize; |
422 masm_->bind(&check_exit_codesize); | 449 masm_->bind(&check_exit_codesize); |
423 #endif | 450 #endif |
424 SetSourcePosition(function()->end_position() - 1); | 451 SetSourcePosition(function()->end_position() - 1); |
425 __ RecordJSReturn(); | 452 __ RecordJSReturn(); |
426 // Do not use the leave instruction here because it is too short to | 453 // Do not use the leave instruction here because it is too short to |
(...skipping 3998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4425 *context_length = 0; | 4452 *context_length = 0; |
4426 return previous_; | 4453 return previous_; |
4427 } | 4454 } |
4428 | 4455 |
4429 | 4456 |
4430 #undef __ | 4457 #undef __ |
4431 | 4458 |
4432 } } // namespace v8::internal | 4459 } } // namespace v8::internal |
4433 | 4460 |
4434 #endif // V8_TARGET_ARCH_IA32 | 4461 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |