| 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 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 if (false_label_ != fall_through_) __ jmp(false_label_); | 631 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 632 } | 632 } |
| 633 } | 633 } |
| 634 | 634 |
| 635 | 635 |
| 636 void FullCodeGenerator::DoTest(Expression* condition, | 636 void FullCodeGenerator::DoTest(Expression* condition, |
| 637 Label* if_true, | 637 Label* if_true, |
| 638 Label* if_false, | 638 Label* if_false, |
| 639 Label* fall_through) { | 639 Label* fall_through) { |
| 640 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 640 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 641 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 641 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
| 642 __ test(result_register(), result_register()); | 642 __ test(result_register(), result_register()); |
| 643 // The stub returns nonzero for true. | 643 // The stub returns nonzero for true. |
| 644 Split(not_zero, if_true, if_false, fall_through); | 644 Split(not_zero, if_true, if_false, fall_through); |
| 645 } | 645 } |
| 646 | 646 |
| 647 | 647 |
| 648 void FullCodeGenerator::Split(Condition cc, | 648 void FullCodeGenerator::Split(Condition cc, |
| 649 Label* if_true, | 649 Label* if_true, |
| 650 Label* if_false, | 650 Label* if_false, |
| 651 Label* fall_through) { | 651 Label* fall_through) { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 __ cmp(edx, eax); | 982 __ cmp(edx, eax); |
| 983 __ j(not_equal, &next_test); | 983 __ j(not_equal, &next_test); |
| 984 __ Drop(1); // Switch value is no longer needed. | 984 __ Drop(1); // Switch value is no longer needed. |
| 985 __ jmp(clause->body_target()); | 985 __ jmp(clause->body_target()); |
| 986 __ bind(&slow_case); | 986 __ bind(&slow_case); |
| 987 } | 987 } |
| 988 | 988 |
| 989 // Record position before stub call for type feedback. | 989 // Record position before stub call for type feedback. |
| 990 SetSourcePosition(clause->position()); | 990 SetSourcePosition(clause->position()); |
| 991 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 991 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 992 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 992 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
| 993 patch_site.EmitPatchInfo(); | 993 patch_site.EmitPatchInfo(); |
| 994 __ test(eax, eax); | 994 __ test(eax, eax); |
| 995 __ j(not_equal, &next_test); | 995 __ j(not_equal, &next_test); |
| 996 __ Drop(1); // Switch value is no longer needed. | 996 __ Drop(1); // Switch value is no longer needed. |
| 997 __ jmp(clause->body_target()); | 997 __ jmp(clause->body_target()); |
| 998 } | 998 } |
| 999 | 999 |
| 1000 // Discard the test value and jump to the default if present, otherwise to | 1000 // Discard the test value and jump to the default if present, otherwise to |
| 1001 // the end of the statement. | 1001 // the end of the statement. |
| 1002 __ bind(&next_test); | 1002 __ bind(&next_test); |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 // Load next context in chain. | 1328 // Load next context in chain. |
| 1329 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1329 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
| 1330 __ jmp(&next); | 1330 __ jmp(&next); |
| 1331 __ bind(&fast); | 1331 __ bind(&fast); |
| 1332 } | 1332 } |
| 1333 | 1333 |
| 1334 // All extension objects were empty and it is safe to use a global | 1334 // All extension objects were empty and it is safe to use a global |
| 1335 // load IC call. | 1335 // load IC call. |
| 1336 __ mov(edx, GlobalObjectOperand()); | 1336 __ mov(edx, GlobalObjectOperand()); |
| 1337 __ mov(ecx, var->name()); | 1337 __ mov(ecx, var->name()); |
| 1338 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1338 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
| 1339 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1339 ? NOT_CONTEXTUAL |
| 1340 ? RelocInfo::CODE_TARGET | 1340 : CONTEXTUAL; |
| 1341 : RelocInfo::CODE_TARGET_CONTEXT; | 1341 |
| 1342 CallIC(ic, mode); | 1342 CallLoadIC(mode); |
| 1343 } | 1343 } |
| 1344 | 1344 |
| 1345 | 1345 |
| 1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1347 Label* slow) { | 1347 Label* slow) { |
| 1348 ASSERT(var->IsContextSlot()); | 1348 ASSERT(var->IsContextSlot()); |
| 1349 Register context = esi; | 1349 Register context = esi; |
| 1350 Register temp = ebx; | 1350 Register temp = ebx; |
| 1351 | 1351 |
| 1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 | 1412 |
| 1413 // Three cases: global variables, lookup variables, and all other types of | 1413 // Three cases: global variables, lookup variables, and all other types of |
| 1414 // variables. | 1414 // variables. |
| 1415 switch (var->location()) { | 1415 switch (var->location()) { |
| 1416 case Variable::UNALLOCATED: { | 1416 case Variable::UNALLOCATED: { |
| 1417 Comment cmnt(masm_, "Global variable"); | 1417 Comment cmnt(masm_, "Global variable"); |
| 1418 // Use inline caching. Variable name is passed in ecx and the global | 1418 // Use inline caching. Variable name is passed in ecx and the global |
| 1419 // object in eax. | 1419 // object in eax. |
| 1420 __ mov(edx, GlobalObjectOperand()); | 1420 __ mov(edx, GlobalObjectOperand()); |
| 1421 __ mov(ecx, var->name()); | 1421 __ mov(ecx, var->name()); |
| 1422 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1422 CallLoadIC(CONTEXTUAL); |
| 1423 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 1424 context()->Plug(eax); | 1423 context()->Plug(eax); |
| 1425 break; | 1424 break; |
| 1426 } | 1425 } |
| 1427 | 1426 |
| 1428 case Variable::PARAMETER: | 1427 case Variable::PARAMETER: |
| 1429 case Variable::LOCAL: | 1428 case Variable::LOCAL: |
| 1430 case Variable::CONTEXT: { | 1429 case Variable::CONTEXT: { |
| 1431 Comment cmnt(masm_, var->IsContextSlot() | 1430 Comment cmnt(masm_, var->IsContextSlot() |
| 1432 ? "Context variable" | 1431 ? "Context variable" |
| 1433 : "Stack variable"); | 1432 : "Stack variable"); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 UNREACHABLE(); | 1628 UNREACHABLE(); |
| 1630 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1629 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1631 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1630 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1632 // Fall through. | 1631 // Fall through. |
| 1633 case ObjectLiteral::Property::COMPUTED: | 1632 case ObjectLiteral::Property::COMPUTED: |
| 1634 if (key->value()->IsInternalizedString()) { | 1633 if (key->value()->IsInternalizedString()) { |
| 1635 if (property->emit_store()) { | 1634 if (property->emit_store()) { |
| 1636 VisitForAccumulatorValue(value); | 1635 VisitForAccumulatorValue(value); |
| 1637 __ mov(ecx, Immediate(key->value())); | 1636 __ mov(ecx, Immediate(key->value())); |
| 1638 __ mov(edx, Operand(esp, 0)); | 1637 __ mov(edx, Operand(esp, 0)); |
| 1639 Handle<Code> ic = is_classic_mode() | 1638 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
| 1640 ? isolate()->builtins()->StoreIC_Initialize() | |
| 1641 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 1642 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | |
| 1643 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1639 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1644 } else { | 1640 } else { |
| 1645 VisitForEffect(value); | 1641 VisitForEffect(value); |
| 1646 } | 1642 } |
| 1647 break; | 1643 break; |
| 1648 } | 1644 } |
| 1649 __ push(Operand(esp, 0)); // Duplicate receiver. | 1645 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1650 VisitForStackValue(key); | 1646 VisitForStackValue(key); |
| 1651 VisitForStackValue(value); | 1647 VisitForStackValue(value); |
| 1652 if (property->emit_store()) { | 1648 if (property->emit_store()) { |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2055 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2051 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2056 CallIC(ic); | 2052 CallIC(ic); |
| 2057 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2053 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2058 __ Drop(1); // The key is still on the stack; drop it. | 2054 __ Drop(1); // The key is still on the stack; drop it. |
| 2059 | 2055 |
| 2060 // if (!result.done) goto l_try; | 2056 // if (!result.done) goto l_try; |
| 2061 __ bind(&l_loop); | 2057 __ bind(&l_loop); |
| 2062 __ push(eax); // save result | 2058 __ push(eax); // save result |
| 2063 __ mov(edx, eax); // result | 2059 __ mov(edx, eax); // result |
| 2064 __ mov(ecx, isolate()->factory()->done_string()); // "done" | 2060 __ mov(ecx, isolate()->factory()->done_string()); // "done" |
| 2065 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 2061 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax |
| 2066 CallIC(done_ic); // result.done in eax | |
| 2067 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2062 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2068 CallIC(bool_ic); | 2063 CallIC(bool_ic); |
| 2069 __ test(eax, eax); | 2064 __ test(eax, eax); |
| 2070 __ j(zero, &l_try); | 2065 __ j(zero, &l_try); |
| 2071 | 2066 |
| 2072 // result.value | 2067 // result.value |
| 2073 __ pop(edx); // result | 2068 __ pop(edx); // result |
| 2074 __ mov(ecx, isolate()->factory()->value_string()); // "value" | 2069 __ mov(ecx, isolate()->factory()->value_string()); // "value" |
| 2075 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | 2070 CallLoadIC(NOT_CONTEXTUAL); // result.value in eax |
| 2076 CallIC(value_ic); // result.value in eax | 2071 context()->DropAndPlug(2, eax); // drop iter and g |
| 2077 context()->DropAndPlug(2, eax); // drop iter and g | |
| 2078 break; | 2072 break; |
| 2079 } | 2073 } |
| 2080 } | 2074 } |
| 2081 } | 2075 } |
| 2082 | 2076 |
| 2083 | 2077 |
| 2084 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2078 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2085 Expression *value, | 2079 Expression *value, |
| 2086 JSGeneratorObject::ResumeMode resume_mode) { | 2080 JSGeneratorObject::ResumeMode resume_mode) { |
| 2087 // The value stays in eax, and is ultimately read by the resumed generator, as | 2081 // The value stays in eax, and is ultimately read by the resumed generator, as |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2210 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, | 2204 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, |
| 2211 ecx, edx, kDontSaveFPRegs); | 2205 ecx, edx, kDontSaveFPRegs); |
| 2212 } | 2206 } |
| 2213 | 2207 |
| 2214 | 2208 |
| 2215 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2209 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2216 SetSourcePosition(prop->position()); | 2210 SetSourcePosition(prop->position()); |
| 2217 Literal* key = prop->key()->AsLiteral(); | 2211 Literal* key = prop->key()->AsLiteral(); |
| 2218 ASSERT(!key->value()->IsSmi()); | 2212 ASSERT(!key->value()->IsSmi()); |
| 2219 __ mov(ecx, Immediate(key->value())); | 2213 __ mov(ecx, Immediate(key->value())); |
| 2220 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2214 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2221 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | |
| 2222 } | 2215 } |
| 2223 | 2216 |
| 2224 | 2217 |
| 2225 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2218 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2226 SetSourcePosition(prop->position()); | 2219 SetSourcePosition(prop->position()); |
| 2227 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2220 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2228 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2221 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2229 } | 2222 } |
| 2230 | 2223 |
| 2231 | 2224 |
| 2232 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2225 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2233 Token::Value op, | 2226 Token::Value op, |
| 2234 OverwriteMode mode, | 2227 OverwriteMode mode, |
| 2235 Expression* left, | 2228 Expression* left, |
| 2236 Expression* right) { | 2229 Expression* right) { |
| 2237 // Do combined smi check of the operands. Left operand is on the | 2230 // Do combined smi check of the operands. Left operand is on the |
| 2238 // stack. Right operand is in eax. | 2231 // stack. Right operand is in eax. |
| 2239 Label smi_case, done, stub_call; | 2232 Label smi_case, done, stub_call; |
| 2240 __ pop(edx); | 2233 __ pop(edx); |
| 2241 __ mov(ecx, eax); | 2234 __ mov(ecx, eax); |
| 2242 __ or_(eax, edx); | 2235 __ or_(eax, edx); |
| 2243 JumpPatchSite patch_site(masm_); | 2236 JumpPatchSite patch_site(masm_); |
| 2244 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 2237 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
| 2245 | 2238 |
| 2246 __ bind(&stub_call); | 2239 __ bind(&stub_call); |
| 2247 __ mov(eax, ecx); | 2240 __ mov(eax, ecx); |
| 2248 BinaryOpICStub stub(op, mode); | 2241 BinaryOpICStub stub(op, mode); |
| 2249 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2242 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2250 expr->BinaryOperationFeedbackId()); | 2243 expr->BinaryOperationFeedbackId()); |
| 2251 patch_site.EmitPatchInfo(); | 2244 patch_site.EmitPatchInfo(); |
| 2252 __ jmp(&done, Label::kNear); | 2245 __ jmp(&done, Label::kNear); |
| 2253 | 2246 |
| 2254 // Smi case. | 2247 // Smi case. |
| 2255 __ bind(&smi_case); | 2248 __ bind(&smi_case); |
| 2256 __ mov(eax, edx); // Copy left operand in case of a stub call. | 2249 __ mov(eax, edx); // Copy left operand in case of a stub call. |
| 2257 | 2250 |
| 2258 switch (op) { | 2251 switch (op) { |
| 2259 case Token::SAR: | 2252 case Token::SAR: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 context()->Plug(eax); | 2318 context()->Plug(eax); |
| 2326 } | 2319 } |
| 2327 | 2320 |
| 2328 | 2321 |
| 2329 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2322 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2330 Token::Value op, | 2323 Token::Value op, |
| 2331 OverwriteMode mode) { | 2324 OverwriteMode mode) { |
| 2332 __ pop(edx); | 2325 __ pop(edx); |
| 2333 BinaryOpICStub stub(op, mode); | 2326 BinaryOpICStub stub(op, mode); |
| 2334 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2327 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2335 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2328 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2336 expr->BinaryOperationFeedbackId()); | 2329 expr->BinaryOperationFeedbackId()); |
| 2337 patch_site.EmitPatchInfo(); | 2330 patch_site.EmitPatchInfo(); |
| 2338 context()->Plug(eax); | 2331 context()->Plug(eax); |
| 2339 } | 2332 } |
| 2340 | 2333 |
| 2341 | 2334 |
| 2342 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2335 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2343 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2336 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2344 // ReferenceError' on the left-hand side. | 2337 // ReferenceError' on the left-hand side. |
| 2345 if (!expr->IsValidLeftHandSide()) { | 2338 if (!expr->IsValidLeftHandSide()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2364 EffectContext context(this); | 2357 EffectContext context(this); |
| 2365 EmitVariableAssignment(var, Token::ASSIGN); | 2358 EmitVariableAssignment(var, Token::ASSIGN); |
| 2366 break; | 2359 break; |
| 2367 } | 2360 } |
| 2368 case NAMED_PROPERTY: { | 2361 case NAMED_PROPERTY: { |
| 2369 __ push(eax); // Preserve value. | 2362 __ push(eax); // Preserve value. |
| 2370 VisitForAccumulatorValue(prop->obj()); | 2363 VisitForAccumulatorValue(prop->obj()); |
| 2371 __ mov(edx, eax); | 2364 __ mov(edx, eax); |
| 2372 __ pop(eax); // Restore value. | 2365 __ pop(eax); // Restore value. |
| 2373 __ mov(ecx, prop->key()->AsLiteral()->value()); | 2366 __ mov(ecx, prop->key()->AsLiteral()->value()); |
| 2374 Handle<Code> ic = is_classic_mode() | 2367 CallStoreIC(NOT_CONTEXTUAL); |
| 2375 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2376 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2377 CallIC(ic); | |
| 2378 break; | 2368 break; |
| 2379 } | 2369 } |
| 2380 case KEYED_PROPERTY: { | 2370 case KEYED_PROPERTY: { |
| 2381 __ push(eax); // Preserve value. | 2371 __ push(eax); // Preserve value. |
| 2382 VisitForStackValue(prop->obj()); | 2372 VisitForStackValue(prop->obj()); |
| 2383 VisitForAccumulatorValue(prop->key()); | 2373 VisitForAccumulatorValue(prop->key()); |
| 2384 __ mov(ecx, eax); | 2374 __ mov(ecx, eax); |
| 2385 __ pop(edx); // Receiver. | 2375 __ pop(edx); // Receiver. |
| 2386 __ pop(eax); // Restore value. | 2376 __ pop(eax); // Restore value. |
| 2387 Handle<Code> ic = is_classic_mode() | 2377 Handle<Code> ic = is_classic_mode() |
| 2388 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2378 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2389 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2379 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2390 CallIC(ic); | 2380 CallIC(ic); |
| 2391 break; | 2381 break; |
| 2392 } | 2382 } |
| 2393 } | 2383 } |
| 2394 context()->Plug(eax); | 2384 context()->Plug(eax); |
| 2395 } | 2385 } |
| 2396 | 2386 |
| 2397 | 2387 |
| 2398 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2388 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2399 Token::Value op) { | 2389 Token::Value op) { |
| 2400 if (var->IsUnallocated()) { | 2390 if (var->IsUnallocated()) { |
| 2401 // Global var, const, or let. | 2391 // Global var, const, or let. |
| 2402 __ mov(ecx, var->name()); | 2392 __ mov(ecx, var->name()); |
| 2403 __ mov(edx, GlobalObjectOperand()); | 2393 __ mov(edx, GlobalObjectOperand()); |
| 2404 Handle<Code> ic = is_classic_mode() | 2394 CallStoreIC(CONTEXTUAL); |
| 2405 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2406 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2407 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 2408 | |
| 2409 } else if (op == Token::INIT_CONST) { | 2395 } else if (op == Token::INIT_CONST) { |
| 2410 // Const initializers need a write barrier. | 2396 // Const initializers need a write barrier. |
| 2411 ASSERT(!var->IsParameter()); // No const parameters. | 2397 ASSERT(!var->IsParameter()); // No const parameters. |
| 2412 if (var->IsStackLocal()) { | 2398 if (var->IsStackLocal()) { |
| 2413 Label skip; | 2399 Label skip; |
| 2414 __ mov(edx, StackOperand(var)); | 2400 __ mov(edx, StackOperand(var)); |
| 2415 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2401 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2416 __ j(not_equal, &skip); | 2402 __ j(not_equal, &skip); |
| 2417 __ mov(StackOperand(var), eax); | 2403 __ mov(StackOperand(var), eax); |
| 2418 __ bind(&skip); | 2404 __ bind(&skip); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2492 // esp[0] : receiver | 2478 // esp[0] : receiver |
| 2493 | 2479 |
| 2494 Property* prop = expr->target()->AsProperty(); | 2480 Property* prop = expr->target()->AsProperty(); |
| 2495 ASSERT(prop != NULL); | 2481 ASSERT(prop != NULL); |
| 2496 ASSERT(prop->key()->AsLiteral() != NULL); | 2482 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2497 | 2483 |
| 2498 // Record source code position before IC call. | 2484 // Record source code position before IC call. |
| 2499 SetSourcePosition(expr->position()); | 2485 SetSourcePosition(expr->position()); |
| 2500 __ mov(ecx, prop->key()->AsLiteral()->value()); | 2486 __ mov(ecx, prop->key()->AsLiteral()->value()); |
| 2501 __ pop(edx); | 2487 __ pop(edx); |
| 2502 Handle<Code> ic = is_classic_mode() | 2488 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2503 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2504 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2505 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | |
| 2506 | |
| 2507 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2489 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2508 context()->Plug(eax); | 2490 context()->Plug(eax); |
| 2509 } | 2491 } |
| 2510 | 2492 |
| 2511 | 2493 |
| 2512 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2494 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2513 // Assignment to a property, using a keyed store IC. | 2495 // Assignment to a property, using a keyed store IC. |
| 2514 // eax : value | 2496 // eax : value |
| 2515 // esp[0] : key | 2497 // esp[0] : key |
| 2516 // esp[kPointerSize] : receiver | 2498 // esp[kPointerSize] : receiver |
| 2517 | 2499 |
| 2518 __ pop(ecx); // Key. | 2500 __ pop(ecx); // Key. |
| 2519 __ pop(edx); | 2501 __ pop(edx); |
| 2520 // Record source code position before IC call. | 2502 // Record source code position before IC call. |
| 2521 SetSourcePosition(expr->position()); | 2503 SetSourcePosition(expr->position()); |
| 2522 Handle<Code> ic = is_classic_mode() | 2504 Handle<Code> ic = is_classic_mode() |
| 2523 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2505 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2524 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2525 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2507 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2526 | 2508 |
| 2527 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2528 context()->Plug(eax); | 2510 context()->Plug(eax); |
| 2529 } | 2511 } |
| 2530 | 2512 |
| 2531 | 2513 |
| 2532 void FullCodeGenerator::VisitProperty(Property* expr) { | 2514 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2533 Comment cmnt(masm_, "[ Property"); | 2515 Comment cmnt(masm_, "[ Property"); |
| 2534 Expression* key = expr->key(); | 2516 Expression* key = expr->key(); |
| 2535 | 2517 |
| 2536 if (key->IsPropertyName()) { | 2518 if (key->IsPropertyName()) { |
| 2537 VisitForAccumulatorValue(expr->obj()); | 2519 VisitForAccumulatorValue(expr->obj()); |
| 2538 __ mov(edx, result_register()); | 2520 __ mov(edx, result_register()); |
| 2539 EmitNamedPropertyLoad(expr); | 2521 EmitNamedPropertyLoad(expr); |
| 2540 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2522 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2541 context()->Plug(eax); | 2523 context()->Plug(eax); |
| 2542 } else { | 2524 } else { |
| 2543 VisitForStackValue(expr->obj()); | 2525 VisitForStackValue(expr->obj()); |
| 2544 VisitForAccumulatorValue(expr->key()); | 2526 VisitForAccumulatorValue(expr->key()); |
| 2545 __ pop(edx); // Object. | 2527 __ pop(edx); // Object. |
| 2546 __ mov(ecx, result_register()); // Key. | 2528 __ mov(ecx, result_register()); // Key. |
| 2547 EmitKeyedPropertyLoad(expr); | 2529 EmitKeyedPropertyLoad(expr); |
| 2548 context()->Plug(eax); | 2530 context()->Plug(eax); |
| 2549 } | 2531 } |
| 2550 } | 2532 } |
| 2551 | 2533 |
| 2552 | 2534 |
| 2553 void FullCodeGenerator::CallIC(Handle<Code> code, | 2535 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2554 RelocInfo::Mode rmode, | 2536 ContextualMode mode, |
| 2555 TypeFeedbackId ast_id) { | 2537 TypeFeedbackId ast_id) { |
| 2556 ic_total_count_++; | 2538 ic_total_count_++; |
| 2557 __ call(code, rmode, ast_id); | 2539 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2540 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
| 2558 } | 2541 } |
| 2559 | 2542 |
| 2560 | 2543 |
| 2561 | 2544 |
| 2562 | 2545 |
| 2563 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2546 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2564 Handle<Object> name, | 2547 Handle<Object> name, |
| 2565 RelocInfo::Mode mode) { | 2548 ContextualMode mode) { |
| 2566 // Code common for calls using the IC. | 2549 // Code common for calls using the IC. |
| 2567 ZoneList<Expression*>* args = expr->arguments(); | 2550 ZoneList<Expression*>* args = expr->arguments(); |
| 2568 int arg_count = args->length(); | 2551 int arg_count = args->length(); |
| 2569 { PreservePositionScope scope(masm()->positions_recorder()); | 2552 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2570 for (int i = 0; i < arg_count; i++) { | 2553 for (int i = 0; i < arg_count; i++) { |
| 2571 VisitForStackValue(args->at(i)); | 2554 VisitForStackValue(args->at(i)); |
| 2572 } | 2555 } |
| 2573 __ Set(ecx, Immediate(name)); | 2556 __ Set(ecx, Immediate(name)); |
| 2574 } | 2557 } |
| 2575 // Record source position of the IC call. | 2558 // Record source position of the IC call. |
| 2576 SetSourcePosition(expr->position()); | 2559 SetSourcePosition(expr->position()); |
| 2577 Handle<Code> ic = | 2560 Handle<Code> ic = |
| 2578 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2561 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2579 CallIC(ic, mode, expr->CallFeedbackId()); | 2562 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2563 ? TypeFeedbackId::None() |
| 2564 : expr->CallFeedbackId(); |
| 2565 CallIC(ic, mode, ast_id); |
| 2580 RecordJSReturnSite(expr); | 2566 RecordJSReturnSite(expr); |
| 2581 // Restore context register. | 2567 // Restore context register. |
| 2582 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2568 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2583 context()->Plug(eax); | 2569 context()->Plug(eax); |
| 2584 } | 2570 } |
| 2585 | 2571 |
| 2586 | 2572 |
| 2587 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2573 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2588 Expression* key) { | 2574 Expression* key) { |
| 2589 // Load the key. | 2575 // Load the key. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2601 { PreservePositionScope scope(masm()->positions_recorder()); | 2587 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2602 for (int i = 0; i < arg_count; i++) { | 2588 for (int i = 0; i < arg_count; i++) { |
| 2603 VisitForStackValue(args->at(i)); | 2589 VisitForStackValue(args->at(i)); |
| 2604 } | 2590 } |
| 2605 } | 2591 } |
| 2606 // Record source position of the IC call. | 2592 // Record source position of the IC call. |
| 2607 SetSourcePosition(expr->position()); | 2593 SetSourcePosition(expr->position()); |
| 2608 Handle<Code> ic = | 2594 Handle<Code> ic = |
| 2609 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2595 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
| 2610 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2596 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2611 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2597 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
| 2612 RecordJSReturnSite(expr); | 2598 RecordJSReturnSite(expr); |
| 2613 // Restore context register. | 2599 // Restore context register. |
| 2614 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2600 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2615 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2601 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2616 } | 2602 } |
| 2617 | 2603 |
| 2618 | 2604 |
| 2619 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2605 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2620 // Code common for calls using the call stub. | 2606 // Code common for calls using the call stub. |
| 2621 ZoneList<Expression*>* args = expr->arguments(); | 2607 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2711 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2697 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2712 __ CallStub(&stub); | 2698 __ CallStub(&stub); |
| 2713 RecordJSReturnSite(expr); | 2699 RecordJSReturnSite(expr); |
| 2714 // Restore context register. | 2700 // Restore context register. |
| 2715 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2701 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2716 context()->DropAndPlug(1, eax); | 2702 context()->DropAndPlug(1, eax); |
| 2717 | 2703 |
| 2718 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2704 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 2719 // Push global object as receiver for the call IC. | 2705 // Push global object as receiver for the call IC. |
| 2720 __ push(GlobalObjectOperand()); | 2706 __ push(GlobalObjectOperand()); |
| 2721 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2707 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
| 2722 | |
| 2723 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2708 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 2724 // Call to a lookup slot (dynamically introduced variable). | 2709 // Call to a lookup slot (dynamically introduced variable). |
| 2725 Label slow, done; | 2710 Label slow, done; |
| 2726 { PreservePositionScope scope(masm()->positions_recorder()); | 2711 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2727 // Generate code for loading from variables potentially shadowed by | 2712 // Generate code for loading from variables potentially shadowed by |
| 2728 // eval-introduced variables. | 2713 // eval-introduced variables. |
| 2729 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2714 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2730 } | 2715 } |
| 2731 __ bind(&slow); | 2716 __ bind(&slow); |
| 2732 // Call the runtime to find the function to call (returned in eax) and | 2717 // Call the runtime to find the function to call (returned in eax) and |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2756 // implicitly the global object. | 2741 // implicitly the global object. |
| 2757 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | 2742 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2758 | 2743 |
| 2759 } else if (property != NULL) { | 2744 } else if (property != NULL) { |
| 2760 { PreservePositionScope scope(masm()->positions_recorder()); | 2745 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2761 VisitForStackValue(property->obj()); | 2746 VisitForStackValue(property->obj()); |
| 2762 } | 2747 } |
| 2763 if (property->key()->IsPropertyName()) { | 2748 if (property->key()->IsPropertyName()) { |
| 2764 EmitCallWithIC(expr, | 2749 EmitCallWithIC(expr, |
| 2765 property->key()->AsLiteral()->value(), | 2750 property->key()->AsLiteral()->value(), |
| 2766 RelocInfo::CODE_TARGET); | 2751 NOT_CONTEXTUAL); |
| 2767 } else { | 2752 } else { |
| 2768 EmitKeyedCallWithIC(expr, property->key()); | 2753 EmitKeyedCallWithIC(expr, property->key()); |
| 2769 } | 2754 } |
| 2770 | 2755 |
| 2771 } else { | 2756 } else { |
| 2772 // Call to an arbitrary expression not handled specially above. | 2757 // Call to an arbitrary expression not handled specially above. |
| 2773 { PreservePositionScope scope(masm()->positions_recorder()); | 2758 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2774 VisitForStackValue(callee); | 2759 VisitForStackValue(callee); |
| 2775 } | 2760 } |
| 2776 // Load global receiver object. | 2761 // Load global receiver object. |
| (...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4149 | 4134 |
| 4150 // Push the arguments ("left-to-right"). | 4135 // Push the arguments ("left-to-right"). |
| 4151 int arg_count = args->length(); | 4136 int arg_count = args->length(); |
| 4152 for (int i = 0; i < arg_count; i++) { | 4137 for (int i = 0; i < arg_count; i++) { |
| 4153 VisitForStackValue(args->at(i)); | 4138 VisitForStackValue(args->at(i)); |
| 4154 } | 4139 } |
| 4155 | 4140 |
| 4156 if (expr->is_jsruntime()) { | 4141 if (expr->is_jsruntime()) { |
| 4157 // Call the JS runtime function via a call IC. | 4142 // Call the JS runtime function via a call IC. |
| 4158 __ Set(ecx, Immediate(expr->name())); | 4143 __ Set(ecx, Immediate(expr->name())); |
| 4159 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4144 ContextualMode mode = NOT_CONTEXTUAL; |
| 4160 Handle<Code> ic = | 4145 Handle<Code> ic = |
| 4161 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 4146 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 4162 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 4147 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
| 4163 // Restore context register. | 4148 // Restore context register. |
| 4164 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4149 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4165 } else { | 4150 } else { |
| 4166 // Call the C runtime function. | 4151 // Call the C runtime function. |
| 4167 __ CallRuntime(expr->function(), arg_count); | 4152 __ CallRuntime(expr->function(), arg_count); |
| 4168 } | 4153 } |
| 4169 context()->Plug(eax); | 4154 context()->Plug(eax); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4409 | 4394 |
| 4410 // Record position before stub call. | 4395 // Record position before stub call. |
| 4411 SetSourcePosition(expr->position()); | 4396 SetSourcePosition(expr->position()); |
| 4412 | 4397 |
| 4413 // Call stub for +1/-1. | 4398 // Call stub for +1/-1. |
| 4414 __ bind(&stub_call); | 4399 __ bind(&stub_call); |
| 4415 __ mov(edx, eax); | 4400 __ mov(edx, eax); |
| 4416 __ mov(eax, Immediate(Smi::FromInt(1))); | 4401 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 4417 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); | 4402 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); |
| 4418 CallIC(stub.GetCode(isolate()), | 4403 CallIC(stub.GetCode(isolate()), |
| 4419 RelocInfo::CODE_TARGET, | 4404 NOT_CONTEXTUAL, |
| 4420 expr->CountBinOpFeedbackId()); | 4405 expr->CountBinOpFeedbackId()); |
| 4421 patch_site.EmitPatchInfo(); | 4406 patch_site.EmitPatchInfo(); |
| 4422 __ bind(&done); | 4407 __ bind(&done); |
| 4423 | 4408 |
| 4424 // Store the value returned in eax. | 4409 // Store the value returned in eax. |
| 4425 switch (assign_type) { | 4410 switch (assign_type) { |
| 4426 case VARIABLE: | 4411 case VARIABLE: |
| 4427 if (expr->is_postfix()) { | 4412 if (expr->is_postfix()) { |
| 4428 // Perform the assignment as if via '='. | 4413 // Perform the assignment as if via '='. |
| 4429 { EffectContext context(this); | 4414 { EffectContext context(this); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4441 // Perform the assignment as if via '='. | 4426 // Perform the assignment as if via '='. |
| 4442 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4427 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4443 Token::ASSIGN); | 4428 Token::ASSIGN); |
| 4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4429 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4445 context()->Plug(eax); | 4430 context()->Plug(eax); |
| 4446 } | 4431 } |
| 4447 break; | 4432 break; |
| 4448 case NAMED_PROPERTY: { | 4433 case NAMED_PROPERTY: { |
| 4449 __ mov(ecx, prop->key()->AsLiteral()->value()); | 4434 __ mov(ecx, prop->key()->AsLiteral()->value()); |
| 4450 __ pop(edx); | 4435 __ pop(edx); |
| 4451 Handle<Code> ic = is_classic_mode() | 4436 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4452 ? isolate()->builtins()->StoreIC_Initialize() | |
| 4453 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 4454 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | |
| 4455 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4437 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4456 if (expr->is_postfix()) { | 4438 if (expr->is_postfix()) { |
| 4457 if (!context()->IsEffect()) { | 4439 if (!context()->IsEffect()) { |
| 4458 context()->PlugTOS(); | 4440 context()->PlugTOS(); |
| 4459 } | 4441 } |
| 4460 } else { | 4442 } else { |
| 4461 context()->Plug(eax); | 4443 context()->Plug(eax); |
| 4462 } | 4444 } |
| 4463 break; | 4445 break; |
| 4464 } | 4446 } |
| 4465 case KEYED_PROPERTY: { | 4447 case KEYED_PROPERTY: { |
| 4466 __ pop(ecx); | 4448 __ pop(ecx); |
| 4467 __ pop(edx); | 4449 __ pop(edx); |
| 4468 Handle<Code> ic = is_classic_mode() | 4450 Handle<Code> ic = is_classic_mode() |
| 4469 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4451 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4470 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4452 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4471 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4453 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4472 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4454 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4473 if (expr->is_postfix()) { | 4455 if (expr->is_postfix()) { |
| 4474 // Result is on the stack | 4456 // Result is on the stack |
| 4475 if (!context()->IsEffect()) { | 4457 if (!context()->IsEffect()) { |
| 4476 context()->PlugTOS(); | 4458 context()->PlugTOS(); |
| 4477 } | 4459 } |
| 4478 } else { | 4460 } else { |
| 4479 context()->Plug(eax); | 4461 context()->Plug(eax); |
| 4480 } | 4462 } |
| 4481 break; | 4463 break; |
| 4482 } | 4464 } |
| 4483 } | 4465 } |
| 4484 } | 4466 } |
| 4485 | 4467 |
| 4486 | 4468 |
| 4487 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4469 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4488 VariableProxy* proxy = expr->AsVariableProxy(); | 4470 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4489 ASSERT(!context()->IsEffect()); | 4471 ASSERT(!context()->IsEffect()); |
| 4490 ASSERT(!context()->IsTest()); | 4472 ASSERT(!context()->IsTest()); |
| 4491 | 4473 |
| 4492 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4474 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4493 Comment cmnt(masm_, "Global variable"); | 4475 Comment cmnt(masm_, "Global variable"); |
| 4494 __ mov(edx, GlobalObjectOperand()); | 4476 __ mov(edx, GlobalObjectOperand()); |
| 4495 __ mov(ecx, Immediate(proxy->name())); | 4477 __ mov(ecx, Immediate(proxy->name())); |
| 4496 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 4497 // Use a regular load, not a contextual load, to avoid a reference | 4478 // Use a regular load, not a contextual load, to avoid a reference |
| 4498 // error. | 4479 // error. |
| 4499 CallIC(ic); | 4480 CallLoadIC(NOT_CONTEXTUAL); |
| 4500 PrepareForBailout(expr, TOS_REG); | 4481 PrepareForBailout(expr, TOS_REG); |
| 4501 context()->Plug(eax); | 4482 context()->Plug(eax); |
| 4502 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4483 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4503 Label done, slow; | 4484 Label done, slow; |
| 4504 | 4485 |
| 4505 // Generate code for loading from variables potentially shadowed | 4486 // Generate code for loading from variables potentially shadowed |
| 4506 // by eval-introduced variables. | 4487 // by eval-introduced variables. |
| 4507 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4488 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4508 | 4489 |
| 4509 __ bind(&slow); | 4490 __ bind(&slow); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4651 __ or_(ecx, eax); | 4632 __ or_(ecx, eax); |
| 4652 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4633 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
| 4653 __ cmp(edx, eax); | 4634 __ cmp(edx, eax); |
| 4654 Split(cc, if_true, if_false, NULL); | 4635 Split(cc, if_true, if_false, NULL); |
| 4655 __ bind(&slow_case); | 4636 __ bind(&slow_case); |
| 4656 } | 4637 } |
| 4657 | 4638 |
| 4658 // Record position and call the compare IC. | 4639 // Record position and call the compare IC. |
| 4659 SetSourcePosition(expr->position()); | 4640 SetSourcePosition(expr->position()); |
| 4660 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4641 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4661 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4642 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4662 patch_site.EmitPatchInfo(); | 4643 patch_site.EmitPatchInfo(); |
| 4663 | 4644 |
| 4664 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4645 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4665 __ test(eax, eax); | 4646 __ test(eax, eax); |
| 4666 Split(cc, if_true, if_false, fall_through); | 4647 Split(cc, if_true, if_false, fall_through); |
| 4667 } | 4648 } |
| 4668 } | 4649 } |
| 4669 | 4650 |
| 4670 // Convert the result of the comparison into one expected for this | 4651 // Convert the result of the comparison into one expected for this |
| 4671 // expression's context. | 4652 // expression's context. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4687 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4668 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4688 | 4669 |
| 4689 Handle<Object> nil_value = nil == kNullValue | 4670 Handle<Object> nil_value = nil == kNullValue |
| 4690 ? isolate()->factory()->null_value() | 4671 ? isolate()->factory()->null_value() |
| 4691 : isolate()->factory()->undefined_value(); | 4672 : isolate()->factory()->undefined_value(); |
| 4692 if (expr->op() == Token::EQ_STRICT) { | 4673 if (expr->op() == Token::EQ_STRICT) { |
| 4693 __ cmp(eax, nil_value); | 4674 __ cmp(eax, nil_value); |
| 4694 Split(equal, if_true, if_false, fall_through); | 4675 Split(equal, if_true, if_false, fall_through); |
| 4695 } else { | 4676 } else { |
| 4696 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4677 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4697 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4678 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4698 __ test(eax, eax); | 4679 __ test(eax, eax); |
| 4699 Split(not_zero, if_true, if_false, fall_through); | 4680 Split(not_zero, if_true, if_false, fall_through); |
| 4700 } | 4681 } |
| 4701 context()->Plug(if_true, if_false); | 4682 context()->Plug(if_true, if_false); |
| 4702 } | 4683 } |
| 4703 | 4684 |
| 4704 | 4685 |
| 4705 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4686 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4706 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4687 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4707 context()->Plug(eax); | 4688 context()->Plug(eax); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4913 | 4894 |
| 4914 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4895 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4915 Assembler::target_address_at(call_target_address)); | 4896 Assembler::target_address_at(call_target_address)); |
| 4916 return OSR_AFTER_STACK_CHECK; | 4897 return OSR_AFTER_STACK_CHECK; |
| 4917 } | 4898 } |
| 4918 | 4899 |
| 4919 | 4900 |
| 4920 } } // namespace v8::internal | 4901 } } // namespace v8::internal |
| 4921 | 4902 |
| 4922 #endif // V8_TARGET_ARCH_IA32 | 4903 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |