| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 // Call the runtime to find the boolean value of the source and then | 510 // Call the runtime to find the boolean value of the source and then |
| 511 // translate it into control flow to the pair of labels. | 511 // translate it into control flow to the pair of labels. |
| 512 __ push(result_register()); | 512 __ push(result_register()); |
| 513 __ CallRuntime(Runtime::kToBool, 1); | 513 __ CallRuntime(Runtime::kToBool, 1); |
| 514 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 514 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 515 __ cmp(r0, ip); | 515 __ cmp(r0, ip); |
| 516 Split(eq, if_true, if_false, fall_through); | 516 Split(eq, if_true, if_false, fall_through); |
| 517 } | 517 } |
| 518 | 518 |
| 519 | 519 |
| 520 void FullCodeGenerator::Split(Condition cc, | 520 void FullCodeGenerator::Split(Condition cond, |
| 521 Label* if_true, | 521 Label* if_true, |
| 522 Label* if_false, | 522 Label* if_false, |
| 523 Label* fall_through) { | 523 Label* fall_through) { |
| 524 if (if_false == fall_through) { | 524 if (if_false == fall_through) { |
| 525 __ b(cc, if_true); | 525 __ b(cond, if_true); |
| 526 } else if (if_true == fall_through) { | 526 } else if (if_true == fall_through) { |
| 527 __ b(NegateCondition(cc), if_false); | 527 __ b(NegateCondition(cond), if_false); |
| 528 } else { | 528 } else { |
| 529 __ b(cc, if_true); | 529 __ b(cond, if_true); |
| 530 __ b(if_false); | 530 __ b(if_false); |
| 531 } | 531 } |
| 532 } | 532 } |
| 533 | 533 |
| 534 | 534 |
| 535 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 535 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 536 switch (slot->type()) { | 536 switch (slot->type()) { |
| 537 case Slot::PARAMETER: | 537 case Slot::PARAMETER: |
| 538 case Slot::LOCAL: | 538 case Slot::LOCAL: |
| 539 return MemOperand(fp, SlotOffset(slot)); | 539 return MemOperand(fp, SlotOffset(slot)); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 | 728 |
| 729 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 729 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 730 | 730 |
| 731 ZoneList<CaseClause*>* clauses = stmt->cases(); | 731 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 732 CaseClause* default_clause = NULL; // Can occur anywhere in the list. | 732 CaseClause* default_clause = NULL; // Can occur anywhere in the list. |
| 733 | 733 |
| 734 Label next_test; // Recycled for each test. | 734 Label next_test; // Recycled for each test. |
| 735 // Compile all the tests with branches to their bodies. | 735 // Compile all the tests with branches to their bodies. |
| 736 for (int i = 0; i < clauses->length(); i++) { | 736 for (int i = 0; i < clauses->length(); i++) { |
| 737 CaseClause* clause = clauses->at(i); | 737 CaseClause* clause = clauses->at(i); |
| 738 clause->body_target()->entry_label()->Unuse(); |
| 739 |
| 738 // The default is not a test, but remember it as final fall through. | 740 // The default is not a test, but remember it as final fall through. |
| 739 if (clause->is_default()) { | 741 if (clause->is_default()) { |
| 740 default_clause = clause; | 742 default_clause = clause; |
| 741 continue; | 743 continue; |
| 742 } | 744 } |
| 743 | 745 |
| 744 Comment cmnt(masm_, "[ Case comparison"); | 746 Comment cmnt(masm_, "[ Case comparison"); |
| 745 __ bind(&next_test); | 747 __ bind(&next_test); |
| 746 next_test.Unuse(); | 748 next_test.Unuse(); |
| 747 | 749 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 VisitForAccumulatorValue(stmt->enumerable()); | 813 VisitForAccumulatorValue(stmt->enumerable()); |
| 812 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 814 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 813 __ cmp(r0, ip); | 815 __ cmp(r0, ip); |
| 814 __ b(eq, &exit); | 816 __ b(eq, &exit); |
| 815 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 817 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 816 __ cmp(r0, ip); | 818 __ cmp(r0, ip); |
| 817 __ b(eq, &exit); | 819 __ b(eq, &exit); |
| 818 | 820 |
| 819 // Convert the object to a JS object. | 821 // Convert the object to a JS object. |
| 820 Label convert, done_convert; | 822 Label convert, done_convert; |
| 821 __ BranchOnSmi(r0, &convert); | 823 __ JumpIfSmi(r0, &convert); |
| 822 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 824 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
| 823 __ b(hs, &done_convert); | 825 __ b(hs, &done_convert); |
| 824 __ bind(&convert); | 826 __ bind(&convert); |
| 825 __ push(r0); | 827 __ push(r0); |
| 826 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); | 828 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); |
| 827 __ bind(&done_convert); | 829 __ bind(&done_convert); |
| 828 __ push(r0); | 830 __ push(r0); |
| 829 | 831 |
| 830 // BUG(867): Check cache validity in generated code. This is a fast | 832 // BUG(867): Check cache validity in generated code. This is a fast |
| 831 // case for the JSObject::IsSimpleEnum cache validity checks. If we | 833 // case for the JSObject::IsSimpleEnum cache validity checks. If we |
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 Expression* right, | 1553 Expression* right, |
| 1552 ConstantOperand constant) { | 1554 ConstantOperand constant) { |
| 1553 ASSERT(constant == kNoConstants); // Only handled case. | 1555 ASSERT(constant == kNoConstants); // Only handled case. |
| 1554 EmitBinaryOp(op, mode); | 1556 EmitBinaryOp(op, mode); |
| 1555 } | 1557 } |
| 1556 | 1558 |
| 1557 | 1559 |
| 1558 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1560 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 1559 OverwriteMode mode) { | 1561 OverwriteMode mode) { |
| 1560 __ pop(r1); | 1562 __ pop(r1); |
| 1561 GenericBinaryOpStub stub(op, mode, r1, r0); | 1563 if (op == Token::ADD || op == Token::SUB) { |
| 1562 __ CallStub(&stub); | 1564 TypeRecordingBinaryOpStub stub(op, mode); |
| 1565 __ CallStub(&stub); |
| 1566 } else { |
| 1567 GenericBinaryOpStub stub(op, mode, r1, r0); |
| 1568 __ CallStub(&stub); |
| 1569 } |
| 1563 context()->Plug(r0); | 1570 context()->Plug(r0); |
| 1564 } | 1571 } |
| 1565 | 1572 |
| 1566 | 1573 |
| 1567 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1574 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1568 // Invalid left-hand sides are rewritten to have a 'throw | 1575 // Invalid left-hand sides are rewritten to have a 'throw |
| 1569 // ReferenceError' on the left-hand side. | 1576 // ReferenceError' on the left-hand side. |
| 1570 if (!expr->IsValidLeftHandSide()) { | 1577 if (!expr->IsValidLeftHandSide()) { |
| 1571 VisitForEffect(expr); | 1578 VisitForEffect(expr); |
| 1572 return; | 1579 return; |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1998 if (key != NULL && key->handle()->IsSymbol()) { | 2005 if (key != NULL && key->handle()->IsSymbol()) { |
| 1999 // Call to a named property, use call IC. | 2006 // Call to a named property, use call IC. |
| 2000 { PreservePositionScope scope(masm()->positions_recorder()); | 2007 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2001 VisitForStackValue(prop->obj()); | 2008 VisitForStackValue(prop->obj()); |
| 2002 } | 2009 } |
| 2003 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2010 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2004 } else { | 2011 } else { |
| 2005 // Call to a keyed property. | 2012 // Call to a keyed property. |
| 2006 // For a synthetic property use keyed load IC followed by function call, | 2013 // For a synthetic property use keyed load IC followed by function call, |
| 2007 // for a regular property use keyed CallIC. | 2014 // for a regular property use keyed CallIC. |
| 2008 { PreservePositionScope scope(masm()->positions_recorder()); | |
| 2009 VisitForStackValue(prop->obj()); | |
| 2010 } | |
| 2011 if (prop->is_synthetic()) { | 2015 if (prop->is_synthetic()) { |
| 2012 { PreservePositionScope scope(masm()->positions_recorder()); | 2016 // Do not visit the object and key subexpressions (they are shared |
| 2013 VisitForAccumulatorValue(prop->key()); | 2017 // by all occurrences of the same rewritten parameter). |
| 2014 } | 2018 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 2019 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); |
| 2020 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); |
| 2021 MemOperand operand = EmitSlotSearch(slot, r1); |
| 2022 __ ldr(r1, operand); |
| 2023 |
| 2024 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2025 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
| 2026 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); |
| 2027 |
| 2015 // Record source code position for IC call. | 2028 // Record source code position for IC call. |
| 2016 SetSourcePosition(prop->position()); | 2029 SetSourcePosition(prop->position()); |
| 2017 __ pop(r1); // We do not need to keep the receiver. | |
| 2018 | 2030 |
| 2019 Handle<Code> ic(isolate()->builtins()->builtin( | 2031 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2020 Builtins::KeyedLoadIC_Initialize)); | 2032 Builtins::KeyedLoadIC_Initialize)); |
| 2021 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2033 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2022 __ ldr(r1, GlobalObjectOperand()); | 2034 __ ldr(r1, GlobalObjectOperand()); |
| 2023 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2035 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2024 __ Push(r0, r1); // Function, receiver. | 2036 __ Push(r0, r1); // Function, receiver. |
| 2025 EmitCallWithStub(expr); | 2037 EmitCallWithStub(expr); |
| 2026 } else { | 2038 } else { |
| 2039 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2040 VisitForStackValue(prop->obj()); |
| 2041 } |
| 2027 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2042 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2028 } | 2043 } |
| 2029 } | 2044 } |
| 2030 } else { | 2045 } else { |
| 2031 // Call to some other expression. If the expression is an anonymous | 2046 // Call to some other expression. If the expression is an anonymous |
| 2032 // function literal not called in a loop, mark it as one that should | 2047 // function literal not called in a loop, mark it as one that should |
| 2033 // also use the fast code generator. | 2048 // also use the fast code generator. |
| 2034 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 2049 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 2035 if (lit != NULL && | 2050 if (lit != NULL && |
| 2036 lit->name()->Equals(isolate()->heap()->empty_string()) && | 2051 lit->name()->Equals(isolate()->heap()->empty_string()) && |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2134 | 2149 |
| 2135 VisitForAccumulatorValue(args->at(0)); | 2150 VisitForAccumulatorValue(args->at(0)); |
| 2136 | 2151 |
| 2137 Label materialize_true, materialize_false; | 2152 Label materialize_true, materialize_false; |
| 2138 Label* if_true = NULL; | 2153 Label* if_true = NULL; |
| 2139 Label* if_false = NULL; | 2154 Label* if_false = NULL; |
| 2140 Label* fall_through = NULL; | 2155 Label* fall_through = NULL; |
| 2141 context()->PrepareTest(&materialize_true, &materialize_false, | 2156 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2142 &if_true, &if_false, &fall_through); | 2157 &if_true, &if_false, &fall_through); |
| 2143 | 2158 |
| 2144 __ BranchOnSmi(r0, if_false); | 2159 __ JumpIfSmi(r0, if_false); |
| 2145 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 2160 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 2146 __ cmp(r0, ip); | 2161 __ cmp(r0, ip); |
| 2147 __ b(eq, if_true); | 2162 __ b(eq, if_true); |
| 2148 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2163 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 2149 // Undetectable objects behave like undefined when tested with typeof. | 2164 // Undetectable objects behave like undefined when tested with typeof. |
| 2150 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); | 2165 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| 2151 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 2166 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 2152 __ b(ne, if_false); | 2167 __ b(ne, if_false); |
| 2153 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 2168 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 2154 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 2169 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2166 | 2181 |
| 2167 VisitForAccumulatorValue(args->at(0)); | 2182 VisitForAccumulatorValue(args->at(0)); |
| 2168 | 2183 |
| 2169 Label materialize_true, materialize_false; | 2184 Label materialize_true, materialize_false; |
| 2170 Label* if_true = NULL; | 2185 Label* if_true = NULL; |
| 2171 Label* if_false = NULL; | 2186 Label* if_false = NULL; |
| 2172 Label* fall_through = NULL; | 2187 Label* fall_through = NULL; |
| 2173 context()->PrepareTest(&materialize_true, &materialize_false, | 2188 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2174 &if_true, &if_false, &fall_through); | 2189 &if_true, &if_false, &fall_through); |
| 2175 | 2190 |
| 2176 __ BranchOnSmi(r0, if_false); | 2191 __ JumpIfSmi(r0, if_false); |
| 2177 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 2192 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
| 2178 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2193 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2179 Split(ge, if_true, if_false, fall_through); | 2194 Split(ge, if_true, if_false, fall_through); |
| 2180 | 2195 |
| 2181 context()->Plug(if_true, if_false); | 2196 context()->Plug(if_true, if_false); |
| 2182 } | 2197 } |
| 2183 | 2198 |
| 2184 | 2199 |
| 2185 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 2200 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
| 2186 ASSERT(args->length() == 1); | 2201 ASSERT(args->length() == 1); |
| 2187 | 2202 |
| 2188 VisitForAccumulatorValue(args->at(0)); | 2203 VisitForAccumulatorValue(args->at(0)); |
| 2189 | 2204 |
| 2190 Label materialize_true, materialize_false; | 2205 Label materialize_true, materialize_false; |
| 2191 Label* if_true = NULL; | 2206 Label* if_true = NULL; |
| 2192 Label* if_false = NULL; | 2207 Label* if_false = NULL; |
| 2193 Label* fall_through = NULL; | 2208 Label* fall_through = NULL; |
| 2194 context()->PrepareTest(&materialize_true, &materialize_false, | 2209 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2195 &if_true, &if_false, &fall_through); | 2210 &if_true, &if_false, &fall_through); |
| 2196 | 2211 |
| 2197 __ BranchOnSmi(r0, if_false); | 2212 __ JumpIfSmi(r0, if_false); |
| 2198 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2213 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 2199 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 2214 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
| 2200 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 2215 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 2201 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2216 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2202 Split(ne, if_true, if_false, fall_through); | 2217 Split(ne, if_true, if_false, fall_through); |
| 2203 | 2218 |
| 2204 context()->Plug(if_true, if_false); | 2219 context()->Plug(if_true, if_false); |
| 2205 } | 2220 } |
| 2206 | 2221 |
| 2207 | 2222 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2233 | 2248 |
| 2234 VisitForAccumulatorValue(args->at(0)); | 2249 VisitForAccumulatorValue(args->at(0)); |
| 2235 | 2250 |
| 2236 Label materialize_true, materialize_false; | 2251 Label materialize_true, materialize_false; |
| 2237 Label* if_true = NULL; | 2252 Label* if_true = NULL; |
| 2238 Label* if_false = NULL; | 2253 Label* if_false = NULL; |
| 2239 Label* fall_through = NULL; | 2254 Label* fall_through = NULL; |
| 2240 context()->PrepareTest(&materialize_true, &materialize_false, | 2255 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2241 &if_true, &if_false, &fall_through); | 2256 &if_true, &if_false, &fall_through); |
| 2242 | 2257 |
| 2243 __ BranchOnSmi(r0, if_false); | 2258 __ JumpIfSmi(r0, if_false); |
| 2244 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); | 2259 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); |
| 2245 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2260 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2246 Split(eq, if_true, if_false, fall_through); | 2261 Split(eq, if_true, if_false, fall_through); |
| 2247 | 2262 |
| 2248 context()->Plug(if_true, if_false); | 2263 context()->Plug(if_true, if_false); |
| 2249 } | 2264 } |
| 2250 | 2265 |
| 2251 | 2266 |
| 2252 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 2267 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
| 2253 ASSERT(args->length() == 1); | 2268 ASSERT(args->length() == 1); |
| 2254 | 2269 |
| 2255 VisitForAccumulatorValue(args->at(0)); | 2270 VisitForAccumulatorValue(args->at(0)); |
| 2256 | 2271 |
| 2257 Label materialize_true, materialize_false; | 2272 Label materialize_true, materialize_false; |
| 2258 Label* if_true = NULL; | 2273 Label* if_true = NULL; |
| 2259 Label* if_false = NULL; | 2274 Label* if_false = NULL; |
| 2260 Label* fall_through = NULL; | 2275 Label* fall_through = NULL; |
| 2261 context()->PrepareTest(&materialize_true, &materialize_false, | 2276 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2262 &if_true, &if_false, &fall_through); | 2277 &if_true, &if_false, &fall_through); |
| 2263 | 2278 |
| 2264 __ BranchOnSmi(r0, if_false); | 2279 __ JumpIfSmi(r0, if_false); |
| 2265 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 2280 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 2266 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2281 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2267 Split(eq, if_true, if_false, fall_through); | 2282 Split(eq, if_true, if_false, fall_through); |
| 2268 | 2283 |
| 2269 context()->Plug(if_true, if_false); | 2284 context()->Plug(if_true, if_false); |
| 2270 } | 2285 } |
| 2271 | 2286 |
| 2272 | 2287 |
| 2273 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 2288 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
| 2274 ASSERT(args->length() == 1); | 2289 ASSERT(args->length() == 1); |
| 2275 | 2290 |
| 2276 VisitForAccumulatorValue(args->at(0)); | 2291 VisitForAccumulatorValue(args->at(0)); |
| 2277 | 2292 |
| 2278 Label materialize_true, materialize_false; | 2293 Label materialize_true, materialize_false; |
| 2279 Label* if_true = NULL; | 2294 Label* if_true = NULL; |
| 2280 Label* if_false = NULL; | 2295 Label* if_false = NULL; |
| 2281 Label* fall_through = NULL; | 2296 Label* fall_through = NULL; |
| 2282 context()->PrepareTest(&materialize_true, &materialize_false, | 2297 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2283 &if_true, &if_false, &fall_through); | 2298 &if_true, &if_false, &fall_through); |
| 2284 | 2299 |
| 2285 __ BranchOnSmi(r0, if_false); | 2300 __ JumpIfSmi(r0, if_false); |
| 2286 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 2301 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
| 2287 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2302 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2288 Split(eq, if_true, if_false, fall_through); | 2303 Split(eq, if_true, if_false, fall_through); |
| 2289 | 2304 |
| 2290 context()->Plug(if_true, if_false); | 2305 context()->Plug(if_true, if_false); |
| 2291 } | 2306 } |
| 2292 | 2307 |
| 2293 | 2308 |
| 2294 | 2309 |
| 2295 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 2310 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 } | 2397 } |
| 2383 | 2398 |
| 2384 | 2399 |
| 2385 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { | 2400 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { |
| 2386 ASSERT(args->length() == 1); | 2401 ASSERT(args->length() == 1); |
| 2387 Label done, null, function, non_function_constructor; | 2402 Label done, null, function, non_function_constructor; |
| 2388 | 2403 |
| 2389 VisitForAccumulatorValue(args->at(0)); | 2404 VisitForAccumulatorValue(args->at(0)); |
| 2390 | 2405 |
| 2391 // If the object is a smi, we return null. | 2406 // If the object is a smi, we return null. |
| 2392 __ BranchOnSmi(r0, &null); | 2407 __ JumpIfSmi(r0, &null); |
| 2393 | 2408 |
| 2394 // Check that the object is a JS object but take special care of JS | 2409 // Check that the object is a JS object but take special care of JS |
| 2395 // functions to make sure they have 'Function' as their class. | 2410 // functions to make sure they have 'Function' as their class. |
| 2396 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. | 2411 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. |
| 2397 __ b(lt, &null); | 2412 __ b(lt, &null); |
| 2398 | 2413 |
| 2399 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 2414 // As long as JS_FUNCTION_TYPE is the last instance type and it is |
| 2400 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 2415 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for |
| 2401 // LAST_JS_OBJECT_TYPE. | 2416 // LAST_JS_OBJECT_TYPE. |
| 2402 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 2417 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2533 } | 2548 } |
| 2534 | 2549 |
| 2535 | 2550 |
| 2536 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2551 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
| 2537 ASSERT(args->length() == 1); | 2552 ASSERT(args->length() == 1); |
| 2538 | 2553 |
| 2539 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2554 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 2540 | 2555 |
| 2541 Label done; | 2556 Label done; |
| 2542 // If the object is a smi return the object. | 2557 // If the object is a smi return the object. |
| 2543 __ BranchOnSmi(r0, &done); | 2558 __ JumpIfSmi(r0, &done); |
| 2544 // If the object is not a value type, return the object. | 2559 // If the object is not a value type, return the object. |
| 2545 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); | 2560 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
| 2546 __ b(ne, &done); | 2561 __ b(ne, &done); |
| 2547 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); | 2562 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
| 2548 | 2563 |
| 2549 __ bind(&done); | 2564 __ bind(&done); |
| 2550 context()->Plug(r0); | 2565 context()->Plug(r0); |
| 2551 } | 2566 } |
| 2552 | 2567 |
| 2553 | 2568 |
| 2554 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { | 2569 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { |
| 2555 // Load the arguments on the stack and call the runtime function. | 2570 // Load the arguments on the stack and call the runtime function. |
| 2556 ASSERT(args->length() == 2); | 2571 ASSERT(args->length() == 2); |
| 2557 VisitForStackValue(args->at(0)); | 2572 VisitForStackValue(args->at(0)); |
| 2558 VisitForStackValue(args->at(1)); | 2573 VisitForStackValue(args->at(1)); |
| 2559 __ CallRuntime(Runtime::kMath_pow, 2); | 2574 __ CallRuntime(Runtime::kMath_pow, 2); |
| 2560 context()->Plug(r0); | 2575 context()->Plug(r0); |
| 2561 } | 2576 } |
| 2562 | 2577 |
| 2563 | 2578 |
| 2564 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2579 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| 2565 ASSERT(args->length() == 2); | 2580 ASSERT(args->length() == 2); |
| 2566 | 2581 |
| 2567 VisitForStackValue(args->at(0)); // Load the object. | 2582 VisitForStackValue(args->at(0)); // Load the object. |
| 2568 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2583 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 2569 __ pop(r1); // r0 = value. r1 = object. | 2584 __ pop(r1); // r0 = value. r1 = object. |
| 2570 | 2585 |
| 2571 Label done; | 2586 Label done; |
| 2572 // If the object is a smi, return the value. | 2587 // If the object is a smi, return the value. |
| 2573 __ BranchOnSmi(r1, &done); | 2588 __ JumpIfSmi(r1, &done); |
| 2574 | 2589 |
| 2575 // If the object is not a value type, return the value. | 2590 // If the object is not a value type, return the value. |
| 2576 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 2591 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
| 2577 __ b(ne, &done); | 2592 __ b(ne, &done); |
| 2578 | 2593 |
| 2579 // Store the value. | 2594 // Store the value. |
| 2580 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 2595 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
| 2581 // Update the write barrier. Save the value as it will be | 2596 // Update the write barrier. Save the value as it will be |
| 2582 // overwritten by the write barrier code and is needed afterward. | 2597 // overwritten by the write barrier code and is needed afterward. |
| 2583 __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); | 2598 __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2997 var->AsSlot()->type() != Slot::LOOKUP) { | 3012 var->AsSlot()->type() != Slot::LOOKUP) { |
| 2998 // Result of deleting non-global, non-dynamic variables is false. | 3013 // Result of deleting non-global, non-dynamic variables is false. |
| 2999 // The subexpression does not have side effects. | 3014 // The subexpression does not have side effects. |
| 3000 context()->Plug(false); | 3015 context()->Plug(false); |
| 3001 } else { | 3016 } else { |
| 3002 // Property or variable reference. Call the delete builtin with | 3017 // Property or variable reference. Call the delete builtin with |
| 3003 // object and property name as arguments. | 3018 // object and property name as arguments. |
| 3004 if (prop != NULL) { | 3019 if (prop != NULL) { |
| 3005 VisitForStackValue(prop->obj()); | 3020 VisitForStackValue(prop->obj()); |
| 3006 VisitForStackValue(prop->key()); | 3021 VisitForStackValue(prop->key()); |
| 3022 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); |
| 3007 } else if (var->is_global()) { | 3023 } else if (var->is_global()) { |
| 3008 __ ldr(r1, GlobalObjectOperand()); | 3024 __ ldr(r1, GlobalObjectOperand()); |
| 3009 __ mov(r0, Operand(var->name())); | 3025 __ mov(r0, Operand(var->name())); |
| 3010 __ Push(r1, r0); | 3026 __ Push(r1, r0); |
| 3027 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); |
| 3011 } else { | 3028 } else { |
| 3012 // Non-global variable. Call the runtime to look up the context | 3029 // Non-global variable. Call the runtime to delete from the |
| 3013 // where the variable was introduced. | 3030 // context where the variable was introduced. |
| 3014 __ push(context_register()); | 3031 __ push(context_register()); |
| 3015 __ mov(r2, Operand(var->name())); | 3032 __ mov(r2, Operand(var->name())); |
| 3016 __ push(r2); | 3033 __ push(r2); |
| 3017 __ CallRuntime(Runtime::kLookupContext, 2); | 3034 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 3018 __ push(r0); | |
| 3019 __ mov(r2, Operand(var->name())); | |
| 3020 __ push(r2); | |
| 3021 } | 3035 } |
| 3022 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); | |
| 3023 context()->Plug(r0); | 3036 context()->Plug(r0); |
| 3024 } | 3037 } |
| 3025 break; | 3038 break; |
| 3026 } | 3039 } |
| 3027 | 3040 |
| 3028 case Token::VOID: { | 3041 case Token::VOID: { |
| 3029 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 3042 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 3030 VisitForEffect(expr->expression()); | 3043 VisitForEffect(expr->expression()); |
| 3031 context()->Plug(Heap::kUndefinedValueRootIndex); | 3044 context()->Plug(Heap::kUndefinedValueRootIndex); |
| 3032 break; | 3045 break; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3089 | 3102 |
| 3090 case Token::BIT_NOT: { | 3103 case Token::BIT_NOT: { |
| 3091 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 3104 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
| 3092 // The generic unary operation stub expects the argument to be | 3105 // The generic unary operation stub expects the argument to be |
| 3093 // in the accumulator register r0. | 3106 // in the accumulator register r0. |
| 3094 VisitForAccumulatorValue(expr->expression()); | 3107 VisitForAccumulatorValue(expr->expression()); |
| 3095 Label done; | 3108 Label done; |
| 3096 bool inline_smi_code = ShouldInlineSmiCase(expr->op()); | 3109 bool inline_smi_code = ShouldInlineSmiCase(expr->op()); |
| 3097 if (inline_smi_code) { | 3110 if (inline_smi_code) { |
| 3098 Label call_stub; | 3111 Label call_stub; |
| 3099 __ BranchOnNotSmi(r0, &call_stub); | 3112 __ JumpIfNotSmi(r0, &call_stub); |
| 3100 __ mvn(r0, Operand(r0)); | 3113 __ mvn(r0, Operand(r0)); |
| 3101 // Bit-clear inverted smi-tag. | 3114 // Bit-clear inverted smi-tag. |
| 3102 __ bic(r0, r0, Operand(kSmiTagMask)); | 3115 __ bic(r0, r0, Operand(kSmiTagMask)); |
| 3103 __ b(&done); | 3116 __ b(&done); |
| 3104 __ bind(&call_stub); | 3117 __ bind(&call_stub); |
| 3105 } | 3118 } |
| 3106 bool overwrite = expr->expression()->ResultOverwriteAllowed(); | 3119 bool overwrite = expr->expression()->ResultOverwriteAllowed(); |
| 3107 UnaryOpFlags flags = inline_smi_code | 3120 UnaryOpFlags flags = inline_smi_code |
| 3108 ? NO_UNARY_SMI_CODE_IN_STUB | 3121 ? NO_UNARY_SMI_CODE_IN_STUB |
| 3109 : NO_UNARY_FLAGS; | 3122 : NO_UNARY_FLAGS; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3176 EmitKeyedPropertyLoad(prop); | 3189 EmitKeyedPropertyLoad(prop); |
| 3177 } | 3190 } |
| 3178 } | 3191 } |
| 3179 | 3192 |
| 3180 // We need a second deoptimization point after loading the value | 3193 // We need a second deoptimization point after loading the value |
| 3181 // in case evaluating the property load my have a side effect. | 3194 // in case evaluating the property load my have a side effect. |
| 3182 PrepareForBailout(expr->increment(), TOS_REG); | 3195 PrepareForBailout(expr->increment(), TOS_REG); |
| 3183 | 3196 |
| 3184 // Call ToNumber only if operand is not a smi. | 3197 // Call ToNumber only if operand is not a smi. |
| 3185 Label no_conversion; | 3198 Label no_conversion; |
| 3186 __ BranchOnSmi(r0, &no_conversion); | 3199 __ JumpIfSmi(r0, &no_conversion); |
| 3187 __ push(r0); | 3200 __ push(r0); |
| 3188 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 3201 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); |
| 3189 __ bind(&no_conversion); | 3202 __ bind(&no_conversion); |
| 3190 | 3203 |
| 3191 // Save result for postfix expressions. | 3204 // Save result for postfix expressions. |
| 3192 if (expr->is_postfix()) { | 3205 if (expr->is_postfix()) { |
| 3193 if (!context()->IsEffect()) { | 3206 if (!context()->IsEffect()) { |
| 3194 // Save the result on the stack. If we have a named or keyed property | 3207 // Save the result on the stack. If we have a named or keyed property |
| 3195 // we store the result under the receiver that is currently on top | 3208 // we store the result under the receiver that is currently on top |
| 3196 // of the stack. | 3209 // of the stack. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3210 | 3223 |
| 3211 | 3224 |
| 3212 // Inline smi case if we are in a loop. | 3225 // Inline smi case if we are in a loop. |
| 3213 Label stub_call, done; | 3226 Label stub_call, done; |
| 3214 int count_value = expr->op() == Token::INC ? 1 : -1; | 3227 int count_value = expr->op() == Token::INC ? 1 : -1; |
| 3215 if (ShouldInlineSmiCase(expr->op())) { | 3228 if (ShouldInlineSmiCase(expr->op())) { |
| 3216 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); | 3229 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); |
| 3217 __ b(vs, &stub_call); | 3230 __ b(vs, &stub_call); |
| 3218 // We could eliminate this smi check if we split the code at | 3231 // We could eliminate this smi check if we split the code at |
| 3219 // the first smi check before calling ToNumber. | 3232 // the first smi check before calling ToNumber. |
| 3220 __ BranchOnSmi(r0, &done); | 3233 __ JumpIfSmi(r0, &done); |
| 3221 __ bind(&stub_call); | 3234 __ bind(&stub_call); |
| 3222 // Call stub. Undo operation first. | 3235 // Call stub. Undo operation first. |
| 3223 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 3236 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
| 3224 } | 3237 } |
| 3225 __ mov(r1, Operand(Smi::FromInt(count_value))); | 3238 __ mov(r1, Operand(Smi::FromInt(count_value))); |
| 3226 | 3239 |
| 3227 // Record position before stub call. | 3240 // Record position before stub call. |
| 3228 SetSourcePosition(expr->position()); | 3241 SetSourcePosition(expr->position()); |
| 3229 | 3242 |
| 3230 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); | 3243 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3466 __ CallStub(&stub); | 3479 __ CallStub(&stub); |
| 3467 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3480 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3468 // The stub returns 0 for true. | 3481 // The stub returns 0 for true. |
| 3469 __ tst(r0, r0); | 3482 __ tst(r0, r0); |
| 3470 Split(eq, if_true, if_false, fall_through); | 3483 Split(eq, if_true, if_false, fall_through); |
| 3471 break; | 3484 break; |
| 3472 } | 3485 } |
| 3473 | 3486 |
| 3474 default: { | 3487 default: { |
| 3475 VisitForAccumulatorValue(expr->right()); | 3488 VisitForAccumulatorValue(expr->right()); |
| 3476 Condition cc = eq; | 3489 Condition cond = eq; |
| 3477 bool strict = false; | 3490 bool strict = false; |
| 3478 switch (op) { | 3491 switch (op) { |
| 3479 case Token::EQ_STRICT: | 3492 case Token::EQ_STRICT: |
| 3480 strict = true; | 3493 strict = true; |
| 3481 // Fall through | 3494 // Fall through |
| 3482 case Token::EQ: | 3495 case Token::EQ: |
| 3483 cc = eq; | 3496 cond = eq; |
| 3484 __ pop(r1); | 3497 __ pop(r1); |
| 3485 break; | 3498 break; |
| 3486 case Token::LT: | 3499 case Token::LT: |
| 3487 cc = lt; | 3500 cond = lt; |
| 3488 __ pop(r1); | 3501 __ pop(r1); |
| 3489 break; | 3502 break; |
| 3490 case Token::GT: | 3503 case Token::GT: |
| 3491 // Reverse left and right sides to obtain ECMA-262 conversion order. | 3504 // Reverse left and right sides to obtain ECMA-262 conversion order. |
| 3492 cc = lt; | 3505 cond = lt; |
| 3493 __ mov(r1, result_register()); | 3506 __ mov(r1, result_register()); |
| 3494 __ pop(r0); | 3507 __ pop(r0); |
| 3495 break; | 3508 break; |
| 3496 case Token::LTE: | 3509 case Token::LTE: |
| 3497 // Reverse left and right sides to obtain ECMA-262 conversion order. | 3510 // Reverse left and right sides to obtain ECMA-262 conversion order. |
| 3498 cc = ge; | 3511 cond = ge; |
| 3499 __ mov(r1, result_register()); | 3512 __ mov(r1, result_register()); |
| 3500 __ pop(r0); | 3513 __ pop(r0); |
| 3501 break; | 3514 break; |
| 3502 case Token::GTE: | 3515 case Token::GTE: |
| 3503 cc = ge; | 3516 cond = ge; |
| 3504 __ pop(r1); | 3517 __ pop(r1); |
| 3505 break; | 3518 break; |
| 3506 case Token::IN: | 3519 case Token::IN: |
| 3507 case Token::INSTANCEOF: | 3520 case Token::INSTANCEOF: |
| 3508 default: | 3521 default: |
| 3509 UNREACHABLE(); | 3522 UNREACHABLE(); |
| 3510 } | 3523 } |
| 3511 | 3524 |
| 3512 bool inline_smi_code = ShouldInlineSmiCase(op); | 3525 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 3513 if (inline_smi_code) { | 3526 if (inline_smi_code) { |
| 3514 Label slow_case; | 3527 Label slow_case; |
| 3515 __ orr(r2, r0, Operand(r1)); | 3528 __ orr(r2, r0, Operand(r1)); |
| 3516 __ BranchOnNotSmi(r2, &slow_case); | 3529 __ JumpIfNotSmi(r2, &slow_case); |
| 3517 __ cmp(r1, r0); | 3530 __ cmp(r1, r0); |
| 3518 Split(cc, if_true, if_false, NULL); | 3531 Split(cond, if_true, if_false, NULL); |
| 3519 __ bind(&slow_case); | 3532 __ bind(&slow_case); |
| 3520 } | 3533 } |
| 3521 CompareFlags flags = inline_smi_code | 3534 CompareFlags flags = inline_smi_code |
| 3522 ? NO_SMI_COMPARE_IN_STUB | 3535 ? NO_SMI_COMPARE_IN_STUB |
| 3523 : NO_COMPARE_FLAGS; | 3536 : NO_COMPARE_FLAGS; |
| 3524 CompareStub stub(cc, strict, flags, r1, r0); | 3537 CompareStub stub(cond, strict, flags, r1, r0); |
| 3525 __ CallStub(&stub); | 3538 __ CallStub(&stub); |
| 3526 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3539 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3527 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 3540 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
| 3528 Split(cc, if_true, if_false, fall_through); | 3541 Split(cond, if_true, if_false, fall_through); |
| 3529 } | 3542 } |
| 3530 } | 3543 } |
| 3531 | 3544 |
| 3532 // Convert the result of the comparison into one expected for this | 3545 // Convert the result of the comparison into one expected for this |
| 3533 // expression's context. | 3546 // expression's context. |
| 3534 context()->Plug(if_true, if_false); | 3547 context()->Plug(if_true, if_false); |
| 3535 } | 3548 } |
| 3536 | 3549 |
| 3537 | 3550 |
| 3538 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { | 3551 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3628 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3641 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3629 __ add(pc, r1, Operand(masm_->CodeObject())); | 3642 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3630 } | 3643 } |
| 3631 | 3644 |
| 3632 | 3645 |
| 3633 #undef __ | 3646 #undef __ |
| 3634 | 3647 |
| 3635 } } // namespace v8::internal | 3648 } } // namespace v8::internal |
| 3636 | 3649 |
| 3637 #endif // V8_TARGET_ARCH_ARM | 3650 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |