| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 // o fp: our caller's frame pointer | 123 // o fp: our caller's frame pointer |
| 124 // o sp: stack pointer | 124 // o sp: stack pointer |
| 125 // o lr: return address | 125 // o lr: return address |
| 126 // | 126 // |
| 127 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 127 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
| 128 // frames-arm.h for its layout. | 128 // frames-arm.h for its layout. |
| 129 void FullCodeGenerator::Generate() { | 129 void FullCodeGenerator::Generate() { |
| 130 CompilationInfo* info = info_; | 130 CompilationInfo* info = info_; |
| 131 handler_table_ = | 131 handler_table_ = |
| 132 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 132 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); |
| 133 |
| 134 InitializeFeedbackVector(); |
| 135 |
| 133 profiling_counter_ = isolate()->factory()->NewCell( | 136 profiling_counter_ = isolate()->factory()->NewCell( |
| 134 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); | 137 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); |
| 135 SetFunctionPosition(function()); | 138 SetFunctionPosition(function()); |
| 136 Comment cmnt(masm_, "[ function compiled by full code generator"); | 139 Comment cmnt(masm_, "[ function compiled by full code generator"); |
| 137 | 140 |
| 138 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 141 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 139 | 142 |
| 140 #ifdef DEBUG | 143 #ifdef DEBUG |
| 141 if (strlen(FLAG_stop_at) > 0 && | 144 if (strlen(FLAG_stop_at) > 0 && |
| 142 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 145 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 if (false_label_ != fall_through_) __ b(false_label_); | 664 if (false_label_ != fall_through_) __ b(false_label_); |
| 662 } | 665 } |
| 663 } | 666 } |
| 664 | 667 |
| 665 | 668 |
| 666 void FullCodeGenerator::DoTest(Expression* condition, | 669 void FullCodeGenerator::DoTest(Expression* condition, |
| 667 Label* if_true, | 670 Label* if_true, |
| 668 Label* if_false, | 671 Label* if_false, |
| 669 Label* fall_through) { | 672 Label* fall_through) { |
| 670 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 673 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 671 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); | 674 CallIC(ic, condition->test_id()); |
| 672 __ tst(result_register(), result_register()); | 675 __ tst(result_register(), result_register()); |
| 673 Split(ne, if_true, if_false, fall_through); | 676 Split(ne, if_true, if_false, fall_through); |
| 674 } | 677 } |
| 675 | 678 |
| 676 | 679 |
| 677 void FullCodeGenerator::Split(Condition cond, | 680 void FullCodeGenerator::Split(Condition cond, |
| 678 Label* if_true, | 681 Label* if_true, |
| 679 Label* if_false, | 682 Label* if_false, |
| 680 Label* fall_through) { | 683 Label* fall_through) { |
| 681 if (if_false == fall_through) { | 684 if (if_false == fall_through) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 __ cmp(r1, r0); | 1025 __ cmp(r1, r0); |
| 1023 __ b(ne, &next_test); | 1026 __ b(ne, &next_test); |
| 1024 __ Drop(1); // Switch value is no longer needed. | 1027 __ Drop(1); // Switch value is no longer needed. |
| 1025 __ b(clause->body_target()); | 1028 __ b(clause->body_target()); |
| 1026 __ bind(&slow_case); | 1029 __ bind(&slow_case); |
| 1027 } | 1030 } |
| 1028 | 1031 |
| 1029 // Record position before stub call for type feedback. | 1032 // Record position before stub call for type feedback. |
| 1030 SetSourcePosition(clause->position()); | 1033 SetSourcePosition(clause->position()); |
| 1031 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1034 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1032 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); | 1035 CallIC(ic, clause->CompareId()); |
| 1033 patch_site.EmitPatchInfo(); | 1036 patch_site.EmitPatchInfo(); |
| 1034 | 1037 |
| 1035 Label skip; | 1038 Label skip; |
| 1036 __ b(&skip); | 1039 __ b(&skip); |
| 1037 PrepareForBailout(clause, TOS_REG); | 1040 PrepareForBailout(clause, TOS_REG); |
| 1038 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1041 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 1039 __ cmp(r0, ip); | 1042 __ cmp(r0, ip); |
| 1040 __ b(ne, &next_test); | 1043 __ b(ne, &next_test); |
| 1041 __ Drop(1); | 1044 __ Drop(1); |
| 1042 __ jmp(clause->body_target()); | 1045 __ jmp(clause->body_target()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1067 VisitStatements(clause->statements()); | 1070 VisitStatements(clause->statements()); |
| 1068 } | 1071 } |
| 1069 | 1072 |
| 1070 __ bind(nested_statement.break_label()); | 1073 __ bind(nested_statement.break_label()); |
| 1071 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1074 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1072 } | 1075 } |
| 1073 | 1076 |
| 1074 | 1077 |
| 1075 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 1078 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 1076 Comment cmnt(masm_, "[ ForInStatement"); | 1079 Comment cmnt(masm_, "[ ForInStatement"); |
| 1080 int slot = stmt->ForInFeedbackSlot(); |
| 1077 SetStatementPosition(stmt); | 1081 SetStatementPosition(stmt); |
| 1078 | 1082 |
| 1079 Label loop, exit; | 1083 Label loop, exit; |
| 1080 ForIn loop_statement(this, stmt); | 1084 ForIn loop_statement(this, stmt); |
| 1081 increment_loop_depth(); | 1085 increment_loop_depth(); |
| 1082 | 1086 |
| 1083 // Get the object to enumerate over. If the object is null or undefined, skip | 1087 // Get the object to enumerate over. If the object is null or undefined, skip |
| 1084 // over the loop. See ECMA-262 version 5, section 12.6.4. | 1088 // over the loop. See ECMA-262 version 5, section 12.6.4. |
| 1085 VisitForAccumulatorValue(stmt->enumerable()); | 1089 VisitForAccumulatorValue(stmt->enumerable()); |
| 1086 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1090 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 __ jmp(&loop); | 1160 __ jmp(&loop); |
| 1157 | 1161 |
| 1158 __ bind(&no_descriptors); | 1162 __ bind(&no_descriptors); |
| 1159 __ Drop(1); | 1163 __ Drop(1); |
| 1160 __ jmp(&exit); | 1164 __ jmp(&exit); |
| 1161 | 1165 |
| 1162 // We got a fixed array in register r0. Iterate through that. | 1166 // We got a fixed array in register r0. Iterate through that. |
| 1163 Label non_proxy; | 1167 Label non_proxy; |
| 1164 __ bind(&fixed_array); | 1168 __ bind(&fixed_array); |
| 1165 | 1169 |
| 1166 Handle<Cell> cell = isolate()->factory()->NewCell( | 1170 Handle<Object> feedback = Handle<Object>( |
| 1167 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), | 1171 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker), |
| 1168 isolate())); | 1172 isolate()); |
| 1169 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); | 1173 StoreFeedbackVectorSlot(slot, feedback); |
| 1170 __ Move(r1, cell); | 1174 __ Move(r1, FeedbackVector()); |
| 1171 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); | 1175 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker))); |
| 1172 __ str(r2, FieldMemOperand(r1, Cell::kValueOffset)); | 1176 __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot))); |
| 1173 | 1177 |
| 1174 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check | 1178 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check |
| 1175 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object | 1179 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object |
| 1176 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 1180 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 1177 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); | 1181 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); |
| 1178 __ b(gt, &non_proxy); | 1182 __ b(gt, &non_proxy); |
| 1179 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy | 1183 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy |
| 1180 __ bind(&non_proxy); | 1184 __ bind(&non_proxy); |
| 1181 __ Push(r1, r0); // Smi and array | 1185 __ Push(r1, r0); // Smi and array |
| 1182 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); | 1186 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1685 UNREACHABLE(); | 1689 UNREACHABLE(); |
| 1686 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1690 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1687 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1691 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1688 // Fall through. | 1692 // Fall through. |
| 1689 case ObjectLiteral::Property::COMPUTED: | 1693 case ObjectLiteral::Property::COMPUTED: |
| 1690 if (key->value()->IsInternalizedString()) { | 1694 if (key->value()->IsInternalizedString()) { |
| 1691 if (property->emit_store()) { | 1695 if (property->emit_store()) { |
| 1692 VisitForAccumulatorValue(value); | 1696 VisitForAccumulatorValue(value); |
| 1693 __ mov(r2, Operand(key->value())); | 1697 __ mov(r2, Operand(key->value())); |
| 1694 __ ldr(r1, MemOperand(sp)); | 1698 __ ldr(r1, MemOperand(sp)); |
| 1695 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); | 1699 CallStoreIC(key->LiteralFeedbackId()); |
| 1696 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1700 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1697 } else { | 1701 } else { |
| 1698 VisitForEffect(value); | 1702 VisitForEffect(value); |
| 1699 } | 1703 } |
| 1700 break; | 1704 break; |
| 1701 } | 1705 } |
| 1702 // Duplicate receiver on stack. | 1706 // Duplicate receiver on stack. |
| 1703 __ ldr(r0, MemOperand(sp)); | 1707 __ ldr(r0, MemOperand(sp)); |
| 1704 __ push(r0); | 1708 __ push(r0); |
| 1705 VisitForStackValue(key); | 1709 VisitForStackValue(key); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2087 __ bind(&l_next); | 2091 __ bind(&l_next); |
| 2088 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2092 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
| 2089 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2093 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2090 __ Push(r2, r3, r0); // "next", iter, received | 2094 __ Push(r2, r3, r0); // "next", iter, received |
| 2091 | 2095 |
| 2092 // result = receiver[f](arg); | 2096 // result = receiver[f](arg); |
| 2093 __ bind(&l_call); | 2097 __ bind(&l_call); |
| 2094 __ ldr(r1, MemOperand(sp, kPointerSize)); | 2098 __ ldr(r1, MemOperand(sp, kPointerSize)); |
| 2095 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); | 2099 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); |
| 2096 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2100 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2097 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); | 2101 CallIC(ic, TypeFeedbackId::None()); |
| 2098 __ mov(r1, r0); | 2102 __ mov(r1, r0); |
| 2099 __ str(r1, MemOperand(sp, 2 * kPointerSize)); | 2103 __ str(r1, MemOperand(sp, 2 * kPointerSize)); |
| 2100 CallFunctionStub stub(1, CALL_AS_METHOD); | 2104 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2101 __ CallStub(&stub); | 2105 __ CallStub(&stub); |
| 2102 | 2106 |
| 2103 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2107 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2104 __ Drop(1); // The function is still on the stack; drop it. | 2108 __ Drop(1); // The function is still on the stack; drop it. |
| 2105 | 2109 |
| 2106 // if (!result.done) goto l_try; | 2110 // if (!result.done) goto l_try; |
| 2107 __ bind(&l_loop); | 2111 __ bind(&l_loop); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2284 __ mov(r2, Operand(key->value())); | 2288 __ mov(r2, Operand(key->value())); |
| 2285 // Call load IC. It has arguments receiver and property name r0 and r2. | 2289 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 2286 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2290 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2287 } | 2291 } |
| 2288 | 2292 |
| 2289 | 2293 |
| 2290 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2294 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2291 SetSourcePosition(prop->position()); | 2295 SetSourcePosition(prop->position()); |
| 2292 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 2296 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 2293 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2297 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2294 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2298 CallIC(ic, prop->PropertyFeedbackId()); |
| 2295 } | 2299 } |
| 2296 | 2300 |
| 2297 | 2301 |
| 2298 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2302 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2299 Token::Value op, | 2303 Token::Value op, |
| 2300 OverwriteMode mode, | 2304 OverwriteMode mode, |
| 2301 Expression* left_expr, | 2305 Expression* left_expr, |
| 2302 Expression* right_expr) { | 2306 Expression* right_expr) { |
| 2303 Label done, smi_case, stub_call; | 2307 Label done, smi_case, stub_call; |
| 2304 | 2308 |
| 2305 Register scratch1 = r2; | 2309 Register scratch1 = r2; |
| 2306 Register scratch2 = r3; | 2310 Register scratch2 = r3; |
| 2307 | 2311 |
| 2308 // Get the arguments. | 2312 // Get the arguments. |
| 2309 Register left = r1; | 2313 Register left = r1; |
| 2310 Register right = r0; | 2314 Register right = r0; |
| 2311 __ pop(left); | 2315 __ pop(left); |
| 2312 | 2316 |
| 2313 // Perform combined smi check on both operands. | 2317 // Perform combined smi check on both operands. |
| 2314 __ orr(scratch1, left, Operand(right)); | 2318 __ orr(scratch1, left, Operand(right)); |
| 2315 STATIC_ASSERT(kSmiTag == 0); | 2319 STATIC_ASSERT(kSmiTag == 0); |
| 2316 JumpPatchSite patch_site(masm_); | 2320 JumpPatchSite patch_site(masm_); |
| 2317 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2321 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2318 | 2322 |
| 2319 __ bind(&stub_call); | 2323 __ bind(&stub_call); |
| 2320 BinaryOpICStub stub(op, mode); | 2324 BinaryOpICStub stub(op, mode); |
| 2321 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2325 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2322 expr->BinaryOperationFeedbackId()); | |
| 2323 patch_site.EmitPatchInfo(); | 2326 patch_site.EmitPatchInfo(); |
| 2324 __ jmp(&done); | 2327 __ jmp(&done); |
| 2325 | 2328 |
| 2326 __ bind(&smi_case); | 2329 __ bind(&smi_case); |
| 2327 // Smi case. This code works the same way as the smi-smi case in the type | 2330 // Smi case. This code works the same way as the smi-smi case in the type |
| 2328 // recording binary operation stub, see | 2331 // recording binary operation stub, see |
| 2329 switch (op) { | 2332 switch (op) { |
| 2330 case Token::SAR: | 2333 case Token::SAR: |
| 2331 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2334 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| 2332 __ mov(right, Operand(left, ASR, scratch1)); | 2335 __ mov(right, Operand(left, ASR, scratch1)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2389 context()->Plug(r0); | 2392 context()->Plug(r0); |
| 2390 } | 2393 } |
| 2391 | 2394 |
| 2392 | 2395 |
| 2393 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2396 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2394 Token::Value op, | 2397 Token::Value op, |
| 2395 OverwriteMode mode) { | 2398 OverwriteMode mode) { |
| 2396 __ pop(r1); | 2399 __ pop(r1); |
| 2397 BinaryOpICStub stub(op, mode); | 2400 BinaryOpICStub stub(op, mode); |
| 2398 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2401 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2399 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, | 2402 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); |
| 2400 expr->BinaryOperationFeedbackId()); | |
| 2401 patch_site.EmitPatchInfo(); | 2403 patch_site.EmitPatchInfo(); |
| 2402 context()->Plug(r0); | 2404 context()->Plug(r0); |
| 2403 } | 2405 } |
| 2404 | 2406 |
| 2405 | 2407 |
| 2406 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2408 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2407 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2409 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2408 // ReferenceError' on the left-hand side. | 2410 // ReferenceError' on the left-hand side. |
| 2409 if (!expr->IsValidLeftHandSide()) { | 2411 if (!expr->IsValidLeftHandSide()) { |
| 2410 VisitForEffect(expr); | 2412 VisitForEffect(expr); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2428 EffectContext context(this); | 2430 EffectContext context(this); |
| 2429 EmitVariableAssignment(var, Token::ASSIGN); | 2431 EmitVariableAssignment(var, Token::ASSIGN); |
| 2430 break; | 2432 break; |
| 2431 } | 2433 } |
| 2432 case NAMED_PROPERTY: { | 2434 case NAMED_PROPERTY: { |
| 2433 __ push(r0); // Preserve value. | 2435 __ push(r0); // Preserve value. |
| 2434 VisitForAccumulatorValue(prop->obj()); | 2436 VisitForAccumulatorValue(prop->obj()); |
| 2435 __ mov(r1, r0); | 2437 __ mov(r1, r0); |
| 2436 __ pop(r0); // Restore value. | 2438 __ pop(r0); // Restore value. |
| 2437 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2439 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2438 CallStoreIC(NOT_CONTEXTUAL); | 2440 CallStoreIC(); |
| 2439 break; | 2441 break; |
| 2440 } | 2442 } |
| 2441 case KEYED_PROPERTY: { | 2443 case KEYED_PROPERTY: { |
| 2442 __ push(r0); // Preserve value. | 2444 __ push(r0); // Preserve value. |
| 2443 VisitForStackValue(prop->obj()); | 2445 VisitForStackValue(prop->obj()); |
| 2444 VisitForAccumulatorValue(prop->key()); | 2446 VisitForAccumulatorValue(prop->key()); |
| 2445 __ mov(r1, r0); | 2447 __ mov(r1, r0); |
| 2446 __ Pop(r0, r2); // r0 = restored value. | 2448 __ Pop(r0, r2); // r0 = restored value. |
| 2447 Handle<Code> ic = is_classic_mode() | 2449 Handle<Code> ic = is_classic_mode() |
| 2448 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2450 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2449 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2451 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2450 CallIC(ic); | 2452 CallIC(ic); |
| 2451 break; | 2453 break; |
| 2452 } | 2454 } |
| 2453 } | 2455 } |
| 2454 context()->Plug(r0); | 2456 context()->Plug(r0); |
| 2455 } | 2457 } |
| 2456 | 2458 |
| 2457 | 2459 |
| 2458 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2460 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2459 Token::Value op) { | 2461 Token::Value op) { |
| 2460 if (var->IsUnallocated()) { | 2462 if (var->IsUnallocated()) { |
| 2461 // Global var, const, or let. | 2463 // Global var, const, or let. |
| 2462 __ mov(r2, Operand(var->name())); | 2464 __ mov(r2, Operand(var->name())); |
| 2463 __ ldr(r1, GlobalObjectOperand()); | 2465 __ ldr(r1, GlobalObjectOperand()); |
| 2464 CallStoreIC(CONTEXTUAL); | 2466 CallStoreIC(); |
| 2465 } else if (op == Token::INIT_CONST) { | 2467 } else if (op == Token::INIT_CONST) { |
| 2466 // Const initializers need a write barrier. | 2468 // Const initializers need a write barrier. |
| 2467 ASSERT(!var->IsParameter()); // No const parameters. | 2469 ASSERT(!var->IsParameter()); // No const parameters. |
| 2468 if (var->IsStackLocal()) { | 2470 if (var->IsStackLocal()) { |
| 2469 __ ldr(r1, StackOperand(var)); | 2471 __ ldr(r1, StackOperand(var)); |
| 2470 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 2472 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
| 2471 __ str(result_register(), StackOperand(var), eq); | 2473 __ str(result_register(), StackOperand(var), eq); |
| 2472 } else { | 2474 } else { |
| 2473 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); | 2475 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); |
| 2474 // Like var declarations, const declarations are hoisted to function | 2476 // Like var declarations, const declarations are hoisted to function |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2548 // Assignment to a property, using a named store IC. | 2550 // Assignment to a property, using a named store IC. |
| 2549 Property* prop = expr->target()->AsProperty(); | 2551 Property* prop = expr->target()->AsProperty(); |
| 2550 ASSERT(prop != NULL); | 2552 ASSERT(prop != NULL); |
| 2551 ASSERT(prop->key()->AsLiteral() != NULL); | 2553 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2552 | 2554 |
| 2553 // Record source code position before IC call. | 2555 // Record source code position before IC call. |
| 2554 SetSourcePosition(expr->position()); | 2556 SetSourcePosition(expr->position()); |
| 2555 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2557 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2556 __ pop(r1); | 2558 __ pop(r1); |
| 2557 | 2559 |
| 2558 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2560 CallStoreIC(expr->AssignmentFeedbackId()); |
| 2559 | 2561 |
| 2560 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2562 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2561 context()->Plug(r0); | 2563 context()->Plug(r0); |
| 2562 } | 2564 } |
| 2563 | 2565 |
| 2564 | 2566 |
| 2565 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2567 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2566 // Assignment to a property, using a keyed store IC. | 2568 // Assignment to a property, using a keyed store IC. |
| 2567 | 2569 |
| 2568 // Record source code position before IC call. | 2570 // Record source code position before IC call. |
| 2569 SetSourcePosition(expr->position()); | 2571 SetSourcePosition(expr->position()); |
| 2570 __ Pop(r2, r1); // r1 = key. | 2572 __ Pop(r2, r1); // r1 = key. |
| 2571 | 2573 |
| 2572 Handle<Code> ic = is_classic_mode() | 2574 Handle<Code> ic = is_classic_mode() |
| 2573 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2575 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2574 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2576 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2575 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); | 2577 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2576 | 2578 |
| 2577 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2579 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2578 context()->Plug(r0); | 2580 context()->Plug(r0); |
| 2579 } | 2581 } |
| 2580 | 2582 |
| 2581 | 2583 |
| 2582 void FullCodeGenerator::VisitProperty(Property* expr) { | 2584 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2583 Comment cmnt(masm_, "[ Property"); | 2585 Comment cmnt(masm_, "[ Property"); |
| 2584 Expression* key = expr->key(); | 2586 Expression* key = expr->key(); |
| 2585 | 2587 |
| 2586 if (key->IsPropertyName()) { | 2588 if (key->IsPropertyName()) { |
| 2587 VisitForAccumulatorValue(expr->obj()); | 2589 VisitForAccumulatorValue(expr->obj()); |
| 2588 EmitNamedPropertyLoad(expr); | 2590 EmitNamedPropertyLoad(expr); |
| 2589 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2591 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2590 context()->Plug(r0); | 2592 context()->Plug(r0); |
| 2591 } else { | 2593 } else { |
| 2592 VisitForStackValue(expr->obj()); | 2594 VisitForStackValue(expr->obj()); |
| 2593 VisitForAccumulatorValue(expr->key()); | 2595 VisitForAccumulatorValue(expr->key()); |
| 2594 __ pop(r1); | 2596 __ pop(r1); |
| 2595 EmitKeyedPropertyLoad(expr); | 2597 EmitKeyedPropertyLoad(expr); |
| 2596 context()->Plug(r0); | 2598 context()->Plug(r0); |
| 2597 } | 2599 } |
| 2598 } | 2600 } |
| 2599 | 2601 |
| 2600 | 2602 |
| 2601 void FullCodeGenerator::CallIC(Handle<Code> code, | 2603 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2602 ContextualMode mode, | |
| 2603 TypeFeedbackId ast_id) { | 2604 TypeFeedbackId ast_id) { |
| 2604 ic_total_count_++; | 2605 ic_total_count_++; |
| 2605 // All calls must have a predictable size in full-codegen code to ensure that | 2606 // All calls must have a predictable size in full-codegen code to ensure that |
| 2606 // the debugger can patch them correctly. | 2607 // the debugger can patch them correctly. |
| 2607 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); | |
| 2608 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, | 2608 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, |
| 2609 NEVER_INLINE_TARGET_ADDRESS); | 2609 NEVER_INLINE_TARGET_ADDRESS); |
| 2610 } | 2610 } |
| 2611 | 2611 |
| 2612 | 2612 |
| 2613 // Code common for calls using the IC. | 2613 // Code common for calls using the IC. |
| 2614 void FullCodeGenerator::EmitCallWithIC(Call* expr) { | 2614 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
| 2615 Expression* callee = expr->expression(); | 2615 Expression* callee = expr->expression(); |
| 2616 ZoneList<Expression*>* args = expr->arguments(); | 2616 ZoneList<Expression*>* args = expr->arguments(); |
| 2617 int arg_count = args->length(); | 2617 int arg_count = args->length(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 int arg_count = args->length(); | 2709 int arg_count = args->length(); |
| 2710 { PreservePositionScope scope(masm()->positions_recorder()); | 2710 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2711 for (int i = 0; i < arg_count; i++) { | 2711 for (int i = 0; i < arg_count; i++) { |
| 2712 VisitForStackValue(args->at(i)); | 2712 VisitForStackValue(args->at(i)); |
| 2713 } | 2713 } |
| 2714 } | 2714 } |
| 2715 // Record source position for debugger. | 2715 // Record source position for debugger. |
| 2716 SetSourcePosition(expr->position()); | 2716 SetSourcePosition(expr->position()); |
| 2717 | 2717 |
| 2718 Handle<Object> uninitialized = | 2718 Handle<Object> uninitialized = |
| 2719 TypeFeedbackCells::UninitializedSentinel(isolate()); | 2719 TypeFeedbackInfo::UninitializedSentinel(isolate()); |
| 2720 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); | 2720 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized); |
| 2721 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); | 2721 __ Move(r2, FeedbackVector()); |
| 2722 __ mov(r2, Operand(cell)); | 2722 __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); |
| 2723 | 2723 |
| 2724 // Record call targets in unoptimized code. | 2724 // Record call targets in unoptimized code. |
| 2725 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); | 2725 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); |
| 2726 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2726 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2727 __ CallStub(&stub, expr->CallFeedbackId()); | 2727 __ CallStub(&stub); |
| 2728 RecordJSReturnSite(expr); | 2728 RecordJSReturnSite(expr); |
| 2729 // Restore context register. | 2729 // Restore context register. |
| 2730 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2730 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2731 context()->DropAndPlug(1, r0); | 2731 context()->DropAndPlug(1, r0); |
| 2732 } | 2732 } |
| 2733 | 2733 |
| 2734 | 2734 |
| 2735 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2735 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2736 // r4: copy of the first argument or undefined if it doesn't exist. | 2736 // r4: copy of the first argument or undefined if it doesn't exist. |
| 2737 if (arg_count > 0) { | 2737 if (arg_count > 0) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2898 // Call the construct call builtin that handles allocation and | 2898 // Call the construct call builtin that handles allocation and |
| 2899 // constructor invocation. | 2899 // constructor invocation. |
| 2900 SetSourcePosition(expr->position()); | 2900 SetSourcePosition(expr->position()); |
| 2901 | 2901 |
| 2902 // Load function and argument count into r1 and r0. | 2902 // Load function and argument count into r1 and r0. |
| 2903 __ mov(r0, Operand(arg_count)); | 2903 __ mov(r0, Operand(arg_count)); |
| 2904 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2904 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 2905 | 2905 |
| 2906 // Record call targets in unoptimized code. | 2906 // Record call targets in unoptimized code. |
| 2907 Handle<Object> uninitialized = | 2907 Handle<Object> uninitialized = |
| 2908 TypeFeedbackCells::UninitializedSentinel(isolate()); | 2908 TypeFeedbackInfo::UninitializedSentinel(isolate()); |
| 2909 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); | 2909 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized); |
| 2910 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); | 2910 __ Move(r2, FeedbackVector()); |
| 2911 __ mov(r2, Operand(cell)); | 2911 __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
| 2912 | 2912 |
| 2913 CallConstructStub stub(RECORD_CALL_TARGET); | 2913 CallConstructStub stub(RECORD_CALL_TARGET); |
| 2914 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); | 2914 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); |
| 2915 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2915 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2916 context()->Plug(r0); | 2916 context()->Plug(r0); |
| 2917 } | 2917 } |
| 2918 | 2918 |
| 2919 | 2919 |
| 2920 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2920 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2921 ZoneList<Expression*>* args = expr->arguments(); | 2921 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4404 | 4404 |
| 4405 | 4405 |
| 4406 __ bind(&stub_call); | 4406 __ bind(&stub_call); |
| 4407 __ mov(r1, r0); | 4407 __ mov(r1, r0); |
| 4408 __ mov(r0, Operand(Smi::FromInt(count_value))); | 4408 __ mov(r0, Operand(Smi::FromInt(count_value))); |
| 4409 | 4409 |
| 4410 // Record position before stub call. | 4410 // Record position before stub call. |
| 4411 SetSourcePosition(expr->position()); | 4411 SetSourcePosition(expr->position()); |
| 4412 | 4412 |
| 4413 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4413 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4414 CallIC(stub.GetCode(isolate()), | 4414 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId()); |
| 4415 NOT_CONTEXTUAL, | |
| 4416 expr->CountBinOpFeedbackId()); | |
| 4417 patch_site.EmitPatchInfo(); | 4415 patch_site.EmitPatchInfo(); |
| 4418 __ bind(&done); | 4416 __ bind(&done); |
| 4419 | 4417 |
| 4420 // Store the value returned in r0. | 4418 // Store the value returned in r0. |
| 4421 switch (assign_type) { | 4419 switch (assign_type) { |
| 4422 case VARIABLE: | 4420 case VARIABLE: |
| 4423 if (expr->is_postfix()) { | 4421 if (expr->is_postfix()) { |
| 4424 { EffectContext context(this); | 4422 { EffectContext context(this); |
| 4425 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4423 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4426 Token::ASSIGN); | 4424 Token::ASSIGN); |
| 4427 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4425 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4428 context.Plug(r0); | 4426 context.Plug(r0); |
| 4429 } | 4427 } |
| 4430 // For all contexts except EffectConstant We have the result on | 4428 // For all contexts except EffectConstant We have the result on |
| 4431 // top of the stack. | 4429 // top of the stack. |
| 4432 if (!context()->IsEffect()) { | 4430 if (!context()->IsEffect()) { |
| 4433 context()->PlugTOS(); | 4431 context()->PlugTOS(); |
| 4434 } | 4432 } |
| 4435 } else { | 4433 } else { |
| 4436 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4434 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4437 Token::ASSIGN); | 4435 Token::ASSIGN); |
| 4438 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4436 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4439 context()->Plug(r0); | 4437 context()->Plug(r0); |
| 4440 } | 4438 } |
| 4441 break; | 4439 break; |
| 4442 case NAMED_PROPERTY: { | 4440 case NAMED_PROPERTY: { |
| 4443 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 4441 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 4444 __ pop(r1); | 4442 __ pop(r1); |
| 4445 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4443 CallStoreIC(expr->CountStoreFeedbackId()); |
| 4446 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4447 if (expr->is_postfix()) { | 4445 if (expr->is_postfix()) { |
| 4448 if (!context()->IsEffect()) { | 4446 if (!context()->IsEffect()) { |
| 4449 context()->PlugTOS(); | 4447 context()->PlugTOS(); |
| 4450 } | 4448 } |
| 4451 } else { | 4449 } else { |
| 4452 context()->Plug(r0); | 4450 context()->Plug(r0); |
| 4453 } | 4451 } |
| 4454 break; | 4452 break; |
| 4455 } | 4453 } |
| 4456 case KEYED_PROPERTY: { | 4454 case KEYED_PROPERTY: { |
| 4457 __ Pop(r2, r1); // r1 = key. r2 = receiver. | 4455 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4458 Handle<Code> ic = is_classic_mode() | 4456 Handle<Code> ic = is_classic_mode() |
| 4459 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4457 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4460 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4458 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4461 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); | 4459 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4462 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4460 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4463 if (expr->is_postfix()) { | 4461 if (expr->is_postfix()) { |
| 4464 if (!context()->IsEffect()) { | 4462 if (!context()->IsEffect()) { |
| 4465 context()->PlugTOS(); | 4463 context()->PlugTOS(); |
| 4466 } | 4464 } |
| 4467 } else { | 4465 } else { |
| 4468 context()->Plug(r0); | 4466 context()->Plug(r0); |
| 4469 } | 4467 } |
| 4470 break; | 4468 break; |
| 4471 } | 4469 } |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4641 __ orr(r2, r0, Operand(r1)); | 4639 __ orr(r2, r0, Operand(r1)); |
| 4642 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4640 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 4643 __ cmp(r1, r0); | 4641 __ cmp(r1, r0); |
| 4644 Split(cond, if_true, if_false, NULL); | 4642 Split(cond, if_true, if_false, NULL); |
| 4645 __ bind(&slow_case); | 4643 __ bind(&slow_case); |
| 4646 } | 4644 } |
| 4647 | 4645 |
| 4648 // Record position and call the compare IC. | 4646 // Record position and call the compare IC. |
| 4649 SetSourcePosition(expr->position()); | 4647 SetSourcePosition(expr->position()); |
| 4650 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4648 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4651 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4649 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4652 patch_site.EmitPatchInfo(); | 4650 patch_site.EmitPatchInfo(); |
| 4653 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4651 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4654 __ cmp(r0, Operand::Zero()); | 4652 __ cmp(r0, Operand::Zero()); |
| 4655 Split(cond, if_true, if_false, fall_through); | 4653 Split(cond, if_true, if_false, fall_through); |
| 4656 } | 4654 } |
| 4657 } | 4655 } |
| 4658 | 4656 |
| 4659 // Convert the result of the comparison into one expected for this | 4657 // Convert the result of the comparison into one expected for this |
| 4660 // expression's context. | 4658 // expression's context. |
| 4661 context()->Plug(if_true, if_false); | 4659 context()->Plug(if_true, if_false); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4676 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4674 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4677 if (expr->op() == Token::EQ_STRICT) { | 4675 if (expr->op() == Token::EQ_STRICT) { |
| 4678 Heap::RootListIndex nil_value = nil == kNullValue ? | 4676 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4679 Heap::kNullValueRootIndex : | 4677 Heap::kNullValueRootIndex : |
| 4680 Heap::kUndefinedValueRootIndex; | 4678 Heap::kUndefinedValueRootIndex; |
| 4681 __ LoadRoot(r1, nil_value); | 4679 __ LoadRoot(r1, nil_value); |
| 4682 __ cmp(r0, r1); | 4680 __ cmp(r0, r1); |
| 4683 Split(eq, if_true, if_false, fall_through); | 4681 Split(eq, if_true, if_false, fall_through); |
| 4684 } else { | 4682 } else { |
| 4685 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4683 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4686 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); | 4684 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 4687 __ cmp(r0, Operand(0)); | 4685 __ cmp(r0, Operand(0)); |
| 4688 Split(ne, if_true, if_false, fall_through); | 4686 Split(ne, if_true, if_false, fall_through); |
| 4689 } | 4687 } |
| 4690 context()->Plug(if_true, if_false); | 4688 context()->Plug(if_true, if_false); |
| 4691 } | 4689 } |
| 4692 | 4690 |
| 4693 | 4691 |
| 4694 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4692 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4695 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4693 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4696 context()->Plug(r0); | 4694 context()->Plug(r0); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4919 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4917 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4920 reinterpret_cast<uint32_t>( | 4918 reinterpret_cast<uint32_t>( |
| 4921 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4919 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4922 return OSR_AFTER_STACK_CHECK; | 4920 return OSR_AFTER_STACK_CHECK; |
| 4923 } | 4921 } |
| 4924 | 4922 |
| 4925 | 4923 |
| 4926 } } // namespace v8::internal | 4924 } } // namespace v8::internal |
| 4927 | 4925 |
| 4928 #endif // V8_TARGET_ARCH_ARM | 4926 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |