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

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 112863002: Merge bleeding_edge 18021:18297 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years 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/ia32/codegen-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('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 // 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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 312
313 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 313 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
314 __ mov(ebx, Immediate(profiling_counter_)); 314 __ mov(ebx, Immediate(profiling_counter_));
315 __ sub(FieldOperand(ebx, Cell::kValueOffset), 315 __ sub(FieldOperand(ebx, Cell::kValueOffset),
316 Immediate(Smi::FromInt(delta))); 316 Immediate(Smi::FromInt(delta)));
317 } 317 }
318 318
319 319
320 void FullCodeGenerator::EmitProfilingCounterReset() { 320 void FullCodeGenerator::EmitProfilingCounterReset() {
321 int reset_value = FLAG_interrupt_budget; 321 int reset_value = FLAG_interrupt_budget;
322 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
323 // Self-optimization is a one-off thing: if it fails, don't try again.
324 reset_value = Smi::kMaxValue;
325 }
326 __ mov(ebx, Immediate(profiling_counter_)); 322 __ mov(ebx, Immediate(profiling_counter_));
327 __ mov(FieldOperand(ebx, Cell::kValueOffset), 323 __ mov(FieldOperand(ebx, Cell::kValueOffset),
328 Immediate(Smi::FromInt(reset_value))); 324 Immediate(Smi::FromInt(reset_value)));
329 } 325 }
330 326
331 327
332 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 328 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
333 Label* back_edge_target) { 329 Label* back_edge_target) {
334 Comment cmnt(masm_, "[ Back edge bookkeeping"); 330 Comment cmnt(masm_, "[ Back edge bookkeeping");
335 Label ok; 331 Label ok;
336 332
337 int weight = 1; 333 ASSERT(back_edge_target->is_bound());
338 if (FLAG_weighted_back_edges) { 334 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
339 ASSERT(back_edge_target->is_bound()); 335 int weight = Min(kMaxBackEdgeWeight,
340 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 336 Max(1, distance / kCodeSizeMultiplier));
341 weight = Min(kMaxBackEdgeWeight,
342 Max(1, distance / kCodeSizeMultiplier));
343 }
344 EmitProfilingCounterDecrement(weight); 337 EmitProfilingCounterDecrement(weight);
345 __ j(positive, &ok, Label::kNear); 338 __ j(positive, &ok, Label::kNear);
346 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 339 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
347 340
348 // Record a mapping of this PC offset to the OSR id. This is used to find 341 // Record a mapping of this PC offset to the OSR id. This is used to find
349 // the AST id from the unoptimized code in order to use it as a key into 342 // the AST id from the unoptimized code in order to use it as a key into
350 // the deoptimization input data found in the optimized code. 343 // the deoptimization input data found in the optimized code.
351 RecordBackEdge(stmt->OsrEntryId()); 344 RecordBackEdge(stmt->OsrEntryId());
352 345
353 EmitProfilingCounterReset(); 346 EmitProfilingCounterReset();
(...skipping 11 matching lines...) Expand all
365 Comment cmnt(masm_, "[ Return sequence"); 358 Comment cmnt(masm_, "[ Return sequence");
366 if (return_label_.is_bound()) { 359 if (return_label_.is_bound()) {
367 __ jmp(&return_label_); 360 __ jmp(&return_label_);
368 } else { 361 } else {
369 // Common return label 362 // Common return label
370 __ bind(&return_label_); 363 __ bind(&return_label_);
371 if (FLAG_trace) { 364 if (FLAG_trace) {
372 __ push(eax); 365 __ push(eax);
373 __ CallRuntime(Runtime::kTraceExit, 1); 366 __ CallRuntime(Runtime::kTraceExit, 1);
374 } 367 }
375 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { 368 // Pretend that the exit is a backwards jump to the entry.
376 // Pretend that the exit is a backwards jump to the entry. 369 int weight = 1;
377 int weight = 1; 370 if (info_->ShouldSelfOptimize()) {
378 if (info_->ShouldSelfOptimize()) { 371 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
379 weight = FLAG_interrupt_budget / FLAG_self_opt_count; 372 } else {
380 } else if (FLAG_weighted_back_edges) { 373 int distance = masm_->pc_offset();
381 int distance = masm_->pc_offset(); 374 weight = Min(kMaxBackEdgeWeight,
382 weight = Min(kMaxBackEdgeWeight, 375 Max(1, distance / kCodeSizeMultiplier));
383 Max(1, distance / kCodeSizeMultiplier));
384 }
385 EmitProfilingCounterDecrement(weight);
386 Label ok;
387 __ j(positive, &ok, Label::kNear);
388 __ push(eax);
389 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
390 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
391 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
392 } else {
393 __ call(isolate()->builtins()->InterruptCheck(),
394 RelocInfo::CODE_TARGET);
395 }
396 __ pop(eax);
397 EmitProfilingCounterReset();
398 __ bind(&ok);
399 } 376 }
377 EmitProfilingCounterDecrement(weight);
378 Label ok;
379 __ j(positive, &ok, Label::kNear);
380 __ push(eax);
381 __ call(isolate()->builtins()->InterruptCheck(),
382 RelocInfo::CODE_TARGET);
383 __ pop(eax);
384 EmitProfilingCounterReset();
385 __ bind(&ok);
400 #ifdef DEBUG 386 #ifdef DEBUG
401 // Add a label for checking the size of the code used for returning. 387 // Add a label for checking the size of the code used for returning.
402 Label check_exit_codesize; 388 Label check_exit_codesize;
403 masm_->bind(&check_exit_codesize); 389 masm_->bind(&check_exit_codesize);
404 #endif 390 #endif
405 SetSourcePosition(function()->end_position() - 1); 391 SetSourcePosition(function()->end_position() - 1);
406 __ RecordJSReturn(); 392 __ RecordJSReturn();
407 // Do not use the leave instruction here because it is too short to 393 // Do not use the leave instruction here because it is too short to
408 // patch with the code required by the debugger. 394 // patch with the code required by the debugger.
409 __ mov(esp, ebp); 395 __ mov(esp, ebp);
(...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 } else { 1684 } else {
1699 context()->Plug(eax); 1685 context()->Plug(eax);
1700 } 1686 }
1701 } 1687 }
1702 1688
1703 1689
1704 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1690 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1705 Comment cmnt(masm_, "[ ArrayLiteral"); 1691 Comment cmnt(masm_, "[ ArrayLiteral");
1706 1692
1707 expr->BuildConstantElements(isolate()); 1693 expr->BuildConstantElements(isolate());
1694 int flags = expr->depth() == 1
1695 ? ArrayLiteral::kShallowElements
1696 : ArrayLiteral::kNoFlags;
1697
1708 ZoneList<Expression*>* subexprs = expr->values(); 1698 ZoneList<Expression*>* subexprs = expr->values();
1709 int length = subexprs->length(); 1699 int length = subexprs->length();
1710 Handle<FixedArray> constant_elements = expr->constant_elements(); 1700 Handle<FixedArray> constant_elements = expr->constant_elements();
1711 ASSERT_EQ(2, constant_elements->length()); 1701 ASSERT_EQ(2, constant_elements->length());
1712 ElementsKind constant_elements_kind = 1702 ElementsKind constant_elements_kind =
1713 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1703 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1714 bool has_constant_fast_elements = 1704 bool has_constant_fast_elements =
1715 IsFastObjectElementsKind(constant_elements_kind); 1705 IsFastObjectElementsKind(constant_elements_kind);
1716 Handle<FixedArrayBase> constant_elements_values( 1706 Handle<FixedArrayBase> constant_elements_values(
1717 FixedArrayBase::cast(constant_elements->get(1))); 1707 FixedArrayBase::cast(constant_elements->get(1)));
1718 1708
1709 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites
1710 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE;
1711 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1712 // If the only customer of allocation sites is transitioning, then
1713 // we can turn it off if we don't have anywhere else to transition to.
1714 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1715 }
1716
1719 Heap* heap = isolate()->heap(); 1717 Heap* heap = isolate()->heap();
1720 if (has_constant_fast_elements && 1718 if (has_constant_fast_elements &&
1721 constant_elements_values->map() == heap->fixed_cow_array_map()) { 1719 constant_elements_values->map() == heap->fixed_cow_array_map()) {
1722 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1720 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
1723 // change, so it's possible to specialize the stub in advance. 1721 // change, so it's possible to specialize the stub in advance.
1724 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); 1722 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1725 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1723 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1726 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset)); 1724 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
1727 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); 1725 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1728 __ mov(ecx, Immediate(constant_elements)); 1726 __ mov(ecx, Immediate(constant_elements));
1729 FastCloneShallowArrayStub stub( 1727 FastCloneShallowArrayStub stub(
1730 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, 1728 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
1731 DONT_TRACK_ALLOCATION_SITE, 1729 allocation_site_mode,
1732 length); 1730 length);
1733 __ CallStub(&stub); 1731 __ CallStub(&stub);
1734 } else if (expr->depth() > 1 || Serializer::enabled() || 1732 } else if (expr->depth() > 1 || Serializer::enabled() ||
1735 length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1733 length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1736 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1734 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1737 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 1735 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
1738 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1736 __ push(Immediate(Smi::FromInt(expr->literal_index())));
1739 __ push(Immediate(constant_elements)); 1737 __ push(Immediate(constant_elements));
1740 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1738 __ push(Immediate(Smi::FromInt(flags)));
1739 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1741 } else { 1740 } else {
1742 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || 1741 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
1743 FLAG_smi_only_arrays); 1742 FLAG_smi_only_arrays);
1744 FastCloneShallowArrayStub::Mode mode = 1743 FastCloneShallowArrayStub::Mode mode =
1745 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; 1744 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
1746 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites
1747 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE;
1748 1745
1749 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1746 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
1750 // change, so it's possible to specialize the stub in advance. 1747 // change, so it's possible to specialize the stub in advance.
1751 if (has_constant_fast_elements) { 1748 if (has_constant_fast_elements) {
1752 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; 1749 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS;
1753 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1754 } 1750 }
1755 1751
1756 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1752 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1757 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset)); 1753 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
1758 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); 1754 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1759 __ mov(ecx, Immediate(constant_elements)); 1755 __ mov(ecx, Immediate(constant_elements));
1760 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length); 1756 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length);
1761 __ CallStub(&stub); 1757 __ CallStub(&stub);
1762 } 1758 }
1763 1759
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 // stack. Right operand is in eax. 2224 // stack. Right operand is in eax.
2229 Label smi_case, done, stub_call; 2225 Label smi_case, done, stub_call;
2230 __ pop(edx); 2226 __ pop(edx);
2231 __ mov(ecx, eax); 2227 __ mov(ecx, eax);
2232 __ or_(eax, edx); 2228 __ or_(eax, edx);
2233 JumpPatchSite patch_site(masm_); 2229 JumpPatchSite patch_site(masm_);
2234 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 2230 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2235 2231
2236 __ bind(&stub_call); 2232 __ bind(&stub_call);
2237 __ mov(eax, ecx); 2233 __ mov(eax, ecx);
2238 BinaryOpStub stub(op, mode); 2234 BinaryOpICStub stub(op, mode);
2239 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2235 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
2240 expr->BinaryOperationFeedbackId()); 2236 expr->BinaryOperationFeedbackId());
2241 patch_site.EmitPatchInfo(); 2237 patch_site.EmitPatchInfo();
2242 __ jmp(&done, Label::kNear); 2238 __ jmp(&done, Label::kNear);
2243 2239
2244 // Smi case. 2240 // Smi case.
2245 __ bind(&smi_case); 2241 __ bind(&smi_case);
2246 __ mov(eax, edx); // Copy left operand in case of a stub call. 2242 __ mov(eax, edx); // Copy left operand in case of a stub call.
2247 2243
2248 switch (op) { 2244 switch (op) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2313 2309
2314 __ bind(&done); 2310 __ bind(&done);
2315 context()->Plug(eax); 2311 context()->Plug(eax);
2316 } 2312 }
2317 2313
2318 2314
2319 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2315 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2320 Token::Value op, 2316 Token::Value op,
2321 OverwriteMode mode) { 2317 OverwriteMode mode) {
2322 __ pop(edx); 2318 __ pop(edx);
2323 BinaryOpStub stub(op, mode); 2319 BinaryOpICStub stub(op, mode);
2324 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2320 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2325 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2321 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
2326 expr->BinaryOperationFeedbackId()); 2322 expr->BinaryOperationFeedbackId());
2327 patch_site.EmitPatchInfo(); 2323 patch_site.EmitPatchInfo();
2328 context()->Plug(eax); 2324 context()->Plug(eax);
2329 } 2325 }
2330 2326
2331 2327
2332 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2328 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2333 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2329 // Invalid left-hand sides are rewritten by the parser to have a 'throw
(...skipping 2063 matching lines...) Expand 10 before | Expand all | Expand 10 after
4397 } 4393 }
4398 } 4394 }
4399 4395
4400 // Record position before stub call. 4396 // Record position before stub call.
4401 SetSourcePosition(expr->position()); 4397 SetSourcePosition(expr->position());
4402 4398
4403 // Call stub for +1/-1. 4399 // Call stub for +1/-1.
4404 __ bind(&stub_call); 4400 __ bind(&stub_call);
4405 __ mov(edx, eax); 4401 __ mov(edx, eax);
4406 __ mov(eax, Immediate(Smi::FromInt(1))); 4402 __ mov(eax, Immediate(Smi::FromInt(1)));
4407 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 4403 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4408 CallIC(stub.GetCode(isolate()), 4404 CallIC(stub.GetCode(isolate()),
4409 RelocInfo::CODE_TARGET, 4405 RelocInfo::CODE_TARGET,
4410 expr->CountBinOpFeedbackId()); 4406 expr->CountBinOpFeedbackId());
4411 patch_site.EmitPatchInfo(); 4407 patch_site.EmitPatchInfo();
4412 __ bind(&done); 4408 __ bind(&done);
4413 4409
4414 // Store the value returned in eax. 4410 // Store the value returned in eax.
4415 switch (assign_type) { 4411 switch (assign_type) {
4416 case VARIABLE: 4412 case VARIABLE:
4417 if (expr->is_postfix()) { 4413 if (expr->is_postfix()) {
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
4830 *stack_depth = 0; 4826 *stack_depth = 0;
4831 *context_length = 0; 4827 *context_length = 0;
4832 return previous_; 4828 return previous_;
4833 } 4829 }
4834 4830
4835 #undef __ 4831 #undef __
4836 4832
4837 4833
4838 static const byte kJnsInstruction = 0x79; 4834 static const byte kJnsInstruction = 0x79;
4839 static const byte kJnsOffset = 0x11; 4835 static const byte kJnsOffset = 0x11;
4840 static const byte kCallInstruction = 0xe8;
4841 static const byte kNopByteOne = 0x66; 4836 static const byte kNopByteOne = 0x66;
4842 static const byte kNopByteTwo = 0x90; 4837 static const byte kNopByteTwo = 0x90;
4838 #ifdef DEBUG
4839 static const byte kCallInstruction = 0xe8;
4840 #endif
4843 4841
4844 4842
4845 void BackEdgeTable::PatchAt(Code* unoptimized_code, 4843 void BackEdgeTable::PatchAt(Code* unoptimized_code,
4846 Address pc, 4844 Address pc,
4847 BackEdgeState target_state, 4845 BackEdgeState target_state,
4848 Code* replacement_code) { 4846 Code* replacement_code) {
4849 Address call_target_address = pc - kIntSize; 4847 Address call_target_address = pc - kIntSize;
4850 Address jns_instr_address = call_target_address - 3; 4848 Address jns_instr_address = call_target_address - 3;
4851 Address jns_offset_address = call_target_address - 2; 4849 Address jns_offset_address = call_target_address - 2;
4852 4850
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4903 4901
4904 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4902 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4905 Assembler::target_address_at(call_target_address)); 4903 Assembler::target_address_at(call_target_address));
4906 return OSR_AFTER_STACK_CHECK; 4904 return OSR_AFTER_STACK_CHECK;
4907 } 4905 }
4908 4906
4909 4907
4910 } } // namespace v8::internal 4908 } } // namespace v8::internal
4911 4909
4912 #endif // V8_TARGET_ARCH_IA32 4910 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698