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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 // sequence is about as long as this Branch would be so it is safe to ignore | 356 // sequence is about as long as this Branch would be so it is safe to ignore |
357 // that. | 357 // that. |
358 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 358 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
359 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 359 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
360 Label ok; | 360 Label ok; |
361 int weight = 1; | 361 int weight = 1; |
362 if (FLAG_weighted_back_edges) { | 362 if (FLAG_weighted_back_edges) { |
363 ASSERT(back_edge_target->is_bound()); | 363 ASSERT(back_edge_target->is_bound()); |
364 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 364 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
365 weight = Min(kMaxBackEdgeWeight, | 365 weight = Min(kMaxBackEdgeWeight, |
366 Max(1, distance / kCodeSizeMultiplier)); | 366 Max(1, distance / kBackEdgeDistanceUnit)); |
367 } | 367 } |
368 EmitProfilingCounterDecrement(weight); | 368 EmitProfilingCounterDecrement(weight); |
369 __ slt(at, a3, zero_reg); | 369 __ slt(at, a3, zero_reg); |
370 __ beq(at, zero_reg, &ok); | 370 __ beq(at, zero_reg, &ok); |
371 // CallStub will emit a li t9 first, so it is safe to use the delay slot. | 371 // CallStub will emit a li t9 first, so it is safe to use the delay slot. |
372 InterruptStub stub; | 372 InterruptStub stub; |
373 __ CallStub(&stub); | 373 __ CallStub(&stub); |
374 // Record a mapping of this PC offset to the OSR id. This is used to find | 374 // Record a mapping of this PC offset to the OSR id. This is used to find |
375 // the AST id from the unoptimized code in order to use it as a key into | 375 // the AST id from the unoptimized code in order to use it as a key into |
376 // the deoptimization input data found in the optimized code. | 376 // the deoptimization input data found in the optimized code. |
(...skipping 22 matching lines...) Expand all Loading... |
399 __ CallRuntime(Runtime::kTraceExit, 1); | 399 __ CallRuntime(Runtime::kTraceExit, 1); |
400 } | 400 } |
401 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { | 401 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { |
402 // Pretend that the exit is a backwards jump to the entry. | 402 // Pretend that the exit is a backwards jump to the entry. |
403 int weight = 1; | 403 int weight = 1; |
404 if (info_->ShouldSelfOptimize()) { | 404 if (info_->ShouldSelfOptimize()) { |
405 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 405 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
406 } else if (FLAG_weighted_back_edges) { | 406 } else if (FLAG_weighted_back_edges) { |
407 int distance = masm_->pc_offset(); | 407 int distance = masm_->pc_offset(); |
408 weight = Min(kMaxBackEdgeWeight, | 408 weight = Min(kMaxBackEdgeWeight, |
409 Max(1, distance / kCodeSizeMultiplier)); | 409 Max(1, distance / kBackEdgeDistanceUnit)); |
410 } | 410 } |
411 EmitProfilingCounterDecrement(weight); | 411 EmitProfilingCounterDecrement(weight); |
412 Label ok; | 412 Label ok; |
413 __ Branch(&ok, ge, a3, Operand(zero_reg)); | 413 __ Branch(&ok, ge, a3, Operand(zero_reg)); |
414 __ push(v0); | 414 __ push(v0); |
415 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { | 415 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { |
416 __ lw(a2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 416 __ lw(a2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
417 __ push(a2); | 417 __ push(a2); |
418 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); | 418 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); |
419 } else { | 419 } else { |
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 for (int i = 0; i < length; i++) { | 1833 for (int i = 0; i < length; i++) { |
1834 Expression* subexpr = subexprs->at(i); | 1834 Expression* subexpr = subexprs->at(i); |
1835 // If the subexpression is a literal or a simple materialized literal it | 1835 // If the subexpression is a literal or a simple materialized literal it |
1836 // is already set in the cloned array. | 1836 // is already set in the cloned array. |
1837 if (subexpr->AsLiteral() != NULL || | 1837 if (subexpr->AsLiteral() != NULL || |
1838 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 1838 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
1839 continue; | 1839 continue; |
1840 } | 1840 } |
1841 | 1841 |
1842 if (!result_saved) { | 1842 if (!result_saved) { |
1843 __ push(v0); // array literal | 1843 __ push(v0); |
1844 __ Push(Smi::FromInt(expr->literal_index())); | |
1845 result_saved = true; | 1844 result_saved = true; |
1846 } | 1845 } |
1847 | 1846 |
1848 VisitForAccumulatorValue(subexpr); | 1847 VisitForAccumulatorValue(subexpr); |
1849 | 1848 |
1850 if (IsFastObjectElementsKind(constant_elements_kind)) { | 1849 if (IsFastObjectElementsKind(constant_elements_kind)) { |
1851 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1850 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
1852 __ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal. | 1851 __ lw(t2, MemOperand(sp)); // Copy of array literal. |
1853 __ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset)); | 1852 __ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset)); |
1854 __ sw(result_register(), FieldMemOperand(a1, offset)); | 1853 __ sw(result_register(), FieldMemOperand(a1, offset)); |
1855 // Update the write barrier for the array store. | 1854 // Update the write barrier for the array store. |
1856 __ RecordWriteField(a1, offset, result_register(), a2, | 1855 __ RecordWriteField(a1, offset, result_register(), a2, |
1857 kRAHasBeenSaved, kDontSaveFPRegs, | 1856 kRAHasBeenSaved, kDontSaveFPRegs, |
1858 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); | 1857 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); |
1859 } else { | 1858 } else { |
| 1859 __ lw(a1, MemOperand(sp)); // Copy of array literal. |
| 1860 __ lw(a2, FieldMemOperand(a1, JSObject::kMapOffset)); |
1860 __ li(a3, Operand(Smi::FromInt(i))); | 1861 __ li(a3, Operand(Smi::FromInt(i))); |
| 1862 __ li(t0, Operand(Smi::FromInt(expr->literal_index()))); |
1861 __ mov(a0, result_register()); | 1863 __ mov(a0, result_register()); |
1862 StoreArrayLiteralElementStub stub; | 1864 StoreArrayLiteralElementStub stub; |
1863 __ CallStub(&stub); | 1865 __ CallStub(&stub); |
1864 } | 1866 } |
1865 | 1867 |
1866 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1868 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
1867 } | 1869 } |
1868 if (result_saved) { | 1870 if (result_saved) { |
1869 __ Pop(); // literal index | |
1870 context()->PlugTOS(); | 1871 context()->PlugTOS(); |
1871 } else { | 1872 } else { |
1872 context()->Plug(v0); | 1873 context()->Plug(v0); |
1873 } | 1874 } |
1874 } | 1875 } |
1875 | 1876 |
1876 | 1877 |
1877 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1878 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1878 Comment cmnt(masm_, "[ Assignment"); | 1879 Comment cmnt(masm_, "[ Assignment"); |
1879 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 1880 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2034 | 2035 |
2035 // Initial stack layout is as follows: | 2036 // Initial stack layout is as follows: |
2036 // [sp + 1 * kPointerSize] iter | 2037 // [sp + 1 * kPointerSize] iter |
2037 // [sp + 0 * kPointerSize] g | 2038 // [sp + 0 * kPointerSize] g |
2038 | 2039 |
2039 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; | 2040 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; |
2040 // Initial send value is undefined. | 2041 // Initial send value is undefined. |
2041 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 2042 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
2042 __ Branch(&l_next); | 2043 __ Branch(&l_next); |
2043 | 2044 |
2044 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2045 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } |
2045 __ bind(&l_catch); | 2046 __ bind(&l_catch); |
2046 __ mov(a0, v0); | 2047 __ mov(a0, v0); |
2047 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2048 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
2048 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" | |
2049 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2049 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
2050 __ push(a3); // iter | 2050 __ push(a3); // iter |
2051 __ push(a0); // exception | 2051 __ push(a0); // exception |
| 2052 __ mov(a0, a3); // iter |
| 2053 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" |
| 2054 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2055 CallIC(throw_ic); // iter.throw in a0 |
| 2056 __ mov(a0, v0); |
2052 __ jmp(&l_call); | 2057 __ jmp(&l_call); |
2053 | 2058 |
2054 // try { received = %yield result } | 2059 // try { received = yield result.value } |
2055 // Shuffle the received result above a try handler and yield it without | |
2056 // re-boxing. | |
2057 __ bind(&l_try); | 2060 __ bind(&l_try); |
2058 __ pop(a0); // result | 2061 EmitCreateIteratorResult(false); // pop and box to v0 |
2059 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2062 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2060 const int handler_size = StackHandlerConstants::kSize; | 2063 const int handler_size = StackHandlerConstants::kSize; |
2061 __ push(a0); // result | 2064 __ push(a0); // result |
2062 __ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g | 2065 __ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g |
2063 __ push(a3); // g | 2066 __ push(a3); // g |
2064 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2067 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2065 __ mov(a0, v0); | 2068 __ mov(a0, v0); |
2066 __ lw(context_register(), | 2069 __ lw(context_register(), |
2067 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2070 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2068 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2071 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
2069 __ Branch(&l_resume, ne, a0, Operand(at)); | 2072 __ Branch(&l_resume, ne, a0, Operand(at)); |
2070 __ pop(v0); // result | 2073 __ pop(v0); // result |
2071 EmitReturnSequence(); | 2074 EmitReturnSequence(); |
2072 __ mov(a0, v0); | 2075 __ mov(a0, v0); |
2073 __ bind(&l_resume); // received in a0 | 2076 __ bind(&l_resume); // received in a0 |
2074 __ PopTryHandler(); | 2077 __ PopTryHandler(); |
2075 | 2078 |
2076 // receiver = iter; f = 'next'; arg = received; | 2079 // receiver = iter; f = iter.next; arg = received; |
2077 __ bind(&l_next); | 2080 __ bind(&l_next); |
2078 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" | |
2079 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2081 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
2080 __ push(a3); // iter | 2082 __ push(a3); // iter |
2081 __ push(a0); // received | 2083 __ push(a0); // received |
| 2084 __ mov(a0, a3); // iter |
| 2085 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" |
| 2086 Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2087 CallIC(next_ic); // iter.next in a0 |
| 2088 __ mov(a0, v0); |
2082 | 2089 |
2083 // result = receiver[f](arg); | 2090 // result = f.call(receiver, arg); |
2084 __ bind(&l_call); | 2091 __ bind(&l_call); |
2085 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2092 Label l_call_runtime; |
2086 CallIC(ic); | 2093 __ JumpIfSmi(a0, &l_call_runtime); |
| 2094 __ GetObjectType(a0, a1, a1); |
| 2095 __ Branch(&l_call_runtime, ne, a1, Operand(JS_FUNCTION_TYPE)); |
| 2096 __ mov(a1, a0); |
| 2097 ParameterCount count(1); |
| 2098 __ InvokeFunction(a1, count, CALL_FUNCTION, |
| 2099 NullCallWrapper(), CALL_AS_METHOD); |
2087 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2100 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2101 __ jmp(&l_loop); |
| 2102 __ bind(&l_call_runtime); |
| 2103 __ push(a0); |
| 2104 __ CallRuntime(Runtime::kCall, 3); |
2088 | 2105 |
2089 // if (!result.done) goto l_try; | 2106 // val = result.value; if (!result.done) goto l_try; |
2090 __ bind(&l_loop); | 2107 __ bind(&l_loop); |
2091 __ mov(a0, v0); | 2108 __ mov(a0, v0); |
| 2109 // result.value |
2092 __ push(a0); // save result | 2110 __ push(a0); // save result |
| 2111 __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value" |
| 2112 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2113 CallIC(value_ic); // result.value in a0 |
| 2114 __ mov(a0, v0); |
| 2115 __ pop(a1); // result |
| 2116 __ push(a0); // result.value |
| 2117 __ mov(a0, a1); // result |
2093 __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" | 2118 __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" |
2094 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 2119 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); |
2095 CallIC(done_ic); // result.done in v0 | 2120 CallIC(done_ic); // result.done in v0 |
2096 __ mov(a0, v0); | 2121 __ mov(a0, v0); |
2097 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2122 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
2098 CallIC(bool_ic); | 2123 CallIC(bool_ic); |
2099 __ Branch(&l_try, eq, v0, Operand(zero_reg)); | 2124 __ Branch(&l_try, eq, v0, Operand(zero_reg)); |
2100 | 2125 |
2101 // result.value | 2126 // result.value |
2102 __ pop(a0); // result | 2127 __ pop(v0); // result.value |
2103 __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value" | |
2104 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | |
2105 CallIC(value_ic); // result.value in v0 | |
2106 context()->DropAndPlug(2, v0); // drop iter and g | 2128 context()->DropAndPlug(2, v0); // drop iter and g |
2107 break; | 2129 break; |
2108 } | 2130 } |
2109 } | 2131 } |
2110 } | 2132 } |
2111 | 2133 |
2112 | 2134 |
2113 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2135 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
2114 Expression *value, | 2136 Expression *value, |
2115 JSGeneratorObject::ResumeMode resume_mode) { | 2137 JSGeneratorObject::ResumeMode resume_mode) { |
(...skipping 2811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 *context_length = 0; | 4949 *context_length = 0; |
4928 return previous_; | 4950 return previous_; |
4929 } | 4951 } |
4930 | 4952 |
4931 | 4953 |
4932 #undef __ | 4954 #undef __ |
4933 | 4955 |
4934 } } // namespace v8::internal | 4956 } } // namespace v8::internal |
4935 | 4957 |
4936 #endif // V8_TARGET_ARCH_MIPS | 4958 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |