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

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

Issue 8112008: MIPS: port all relevant commits since the new-gc was landed. (Closed)
Patch Set: rebased on r9598. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips/code-stubs-mips.cc ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 Comment cmnt(masm_, "[ Declarations"); 271 Comment cmnt(masm_, "[ Declarations");
272 scope()->VisitIllegalRedeclaration(this); 272 scope()->VisitIllegalRedeclaration(this);
273 273
274 } else { 274 } else {
275 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 275 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
276 { Comment cmnt(masm_, "[ Declarations"); 276 { Comment cmnt(masm_, "[ Declarations");
277 // For named function expressions, declare the function name as a 277 // For named function expressions, declare the function name as a
278 // constant. 278 // constant.
279 if (scope()->is_function_scope() && scope()->function() != NULL) { 279 if (scope()->is_function_scope() && scope()->function() != NULL) {
280 int ignored = 0; 280 int ignored = 0;
281 EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored); 281 EmitDeclaration(scope()->function(), CONST, NULL, &ignored);
282 } 282 }
283 VisitDeclarations(scope()->declarations()); 283 VisitDeclarations(scope()->declarations());
284 } 284 }
285 285
286 { Comment cmnt(masm_, "[ Stack check"); 286 { Comment cmnt(masm_, "[ Stack check");
287 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 287 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
288 Label ok; 288 Label ok;
289 __ LoadRoot(t0, Heap::kStackLimitRootIndex); 289 __ LoadRoot(t0, Heap::kStackLimitRootIndex);
290 __ Branch(&ok, hs, sp, Operand(t0)); 290 __ Branch(&ok, hs, sp, Operand(t0));
291 StackCheckStub stub; 291 StackCheckStub stub;
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 714
715 if (should_normalize) { 715 if (should_normalize) {
716 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 716 __ LoadRoot(t0, Heap::kTrueValueRootIndex);
717 Split(eq, a0, Operand(t0), if_true, if_false, NULL); 717 Split(eq, a0, Operand(t0), if_true, if_false, NULL);
718 __ bind(&skip); 718 __ bind(&skip);
719 } 719 }
720 } 720 }
721 721
722 722
723 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 723 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
724 Variable::Mode mode, 724 VariableMode mode,
725 FunctionLiteral* function, 725 FunctionLiteral* function,
726 int* global_count) { 726 int* global_count) {
727 // If it was not possible to allocate the variable at compile time, we 727 // If it was not possible to allocate the variable at compile time, we
728 // need to "declare" it at runtime to make sure it actually exists in the 728 // need to "declare" it at runtime to make sure it actually exists in the
729 // local context. 729 // local context.
730 Variable* variable = proxy->var(); 730 Variable* variable = proxy->var();
731 switch (variable->location()) { 731 switch (variable->location()) {
732 case Variable::UNALLOCATED: 732 case Variable::UNALLOCATED:
733 ++(*global_count); 733 ++(*global_count);
734 break; 734 break;
735 735
736 case Variable::PARAMETER: 736 case Variable::PARAMETER:
737 case Variable::LOCAL: 737 case Variable::LOCAL:
738 if (function != NULL) { 738 if (function != NULL) {
739 Comment cmnt(masm_, "[ Declaration"); 739 Comment cmnt(masm_, "[ Declaration");
740 VisitForAccumulatorValue(function); 740 VisitForAccumulatorValue(function);
741 __ sw(result_register(), StackOperand(variable)); 741 __ sw(result_register(), StackOperand(variable));
742 } else if (mode == Variable::CONST || mode == Variable::LET) { 742 } else if (mode == CONST || mode == LET) {
743 Comment cmnt(masm_, "[ Declaration"); 743 Comment cmnt(masm_, "[ Declaration");
744 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 744 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
745 __ sw(t0, StackOperand(variable)); 745 __ sw(t0, StackOperand(variable));
746 } 746 }
747 break; 747 break;
748 748
749 case Variable::CONTEXT: 749 case Variable::CONTEXT:
750 // The variable in the decl always resides in the current function 750 // The variable in the decl always resides in the current function
751 // context. 751 // context.
752 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 752 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
(...skipping 15 matching lines...) Expand all
768 // We know that we have written a function, which is not a smi. 768 // We know that we have written a function, which is not a smi.
769 __ RecordWriteContextSlot(cp, 769 __ RecordWriteContextSlot(cp,
770 offset, 770 offset,
771 result_register(), 771 result_register(),
772 a2, 772 a2,
773 kRAHasBeenSaved, 773 kRAHasBeenSaved,
774 kDontSaveFPRegs, 774 kDontSaveFPRegs,
775 EMIT_REMEMBERED_SET, 775 EMIT_REMEMBERED_SET,
776 OMIT_SMI_CHECK); 776 OMIT_SMI_CHECK);
777 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 777 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
778 } else if (mode == Variable::CONST || mode == Variable::LET) { 778 } else if (mode == CONST || mode == LET) {
779 Comment cmnt(masm_, "[ Declaration"); 779 Comment cmnt(masm_, "[ Declaration");
780 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 780 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
781 __ sw(at, ContextOperand(cp, variable->index())); 781 __ sw(at, ContextOperand(cp, variable->index()));
782 // No write barrier since the_hole_value is in old space. 782 // No write barrier since the_hole_value is in old space.
783 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 783 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
784 } 784 }
785 break; 785 break;
786 786
787 case Variable::LOOKUP: { 787 case Variable::LOOKUP: {
788 Comment cmnt(masm_, "[ Declaration"); 788 Comment cmnt(masm_, "[ Declaration");
789 __ li(a2, Operand(variable->name())); 789 __ li(a2, Operand(variable->name()));
790 // Declaration nodes are always introduced in one of three modes. 790 // Declaration nodes are always introduced in one of three modes.
791 ASSERT(mode == Variable::VAR || 791 ASSERT(mode == VAR || mode == CONST || mode == LET);
792 mode == Variable::CONST || 792 PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE;
793 mode == Variable::LET);
794 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
795 __ li(a1, Operand(Smi::FromInt(attr))); 793 __ li(a1, Operand(Smi::FromInt(attr)));
796 // Push initial value, if any. 794 // Push initial value, if any.
797 // Note: For variables we must not push an initial value (such as 795 // Note: For variables we must not push an initial value (such as
798 // 'undefined') because we may have a (legal) redeclaration and we 796 // 'undefined') because we may have a (legal) redeclaration and we
799 // must not destroy the current value. 797 // must not destroy the current value.
800 if (function != NULL) { 798 if (function != NULL) {
801 __ Push(cp, a2, a1); 799 __ Push(cp, a2, a1);
802 // Push initial value for function declaration. 800 // Push initial value for function declaration.
803 VisitForStackValue(function); 801 VisitForStackValue(function);
804 } else if (mode == Variable::CONST || mode == Variable::LET) { 802 } else if (mode == CONST || mode == LET) {
805 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); 803 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
806 __ Push(cp, a2, a1, a0); 804 __ Push(cp, a2, a1, a0);
807 } else { 805 } else {
808 ASSERT(Smi::FromInt(0) == 0); 806 ASSERT(Smi::FromInt(0) == 0);
809 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. 807 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value.
810 __ Push(cp, a2, a1, a0); 808 __ Push(cp, a2, a1, a0);
811 } 809 }
812 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 810 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
813 break; 811 break;
814 } 812 }
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 1214
1217 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, 1215 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1218 TypeofState typeof_state, 1216 TypeofState typeof_state,
1219 Label* slow, 1217 Label* slow,
1220 Label* done) { 1218 Label* done) {
1221 // Generate fast-case code for variables that might be shadowed by 1219 // Generate fast-case code for variables that might be shadowed by
1222 // eval-introduced variables. Eval is used a lot without 1220 // eval-introduced variables. Eval is used a lot without
1223 // introducing variables. In those cases, we do not want to 1221 // introducing variables. In those cases, we do not want to
1224 // perform a runtime call for all variables in the scope 1222 // perform a runtime call for all variables in the scope
1225 // containing the eval. 1223 // containing the eval.
1226 if (var->mode() == Variable::DYNAMIC_GLOBAL) { 1224 if (var->mode() == DYNAMIC_GLOBAL) {
1227 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1225 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1228 __ Branch(done); 1226 __ Branch(done);
1229 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { 1227 } else if (var->mode() == DYNAMIC_LOCAL) {
1230 Variable* local = var->local_if_not_shadowed(); 1228 Variable* local = var->local_if_not_shadowed();
1231 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); 1229 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow));
1232 if (local->mode() == Variable::CONST) { 1230 if (local->mode() == CONST ||
1231 local->mode() == LET) {
1233 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1232 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1234 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1233 __ subu(at, v0, at); // Sub as compare: at == 0 on eq.
1235 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1234 if (local->mode() == CONST) {
1236 __ movz(v0, a0, at); // Conditional move: return Undefined if TheHole. 1235 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1236 __ movz(v0, a0, at); // Conditional move: return Undefined if TheHole.
1237 } else { // LET
1238 __ Branch(done, ne, at, Operand(zero_reg));
1239 __ li(a0, Operand(var->name()));
1240 __ push(a0);
1241 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1242 }
1237 } 1243 }
1238 __ Branch(done); 1244 __ Branch(done);
1239 } 1245 }
1240 } 1246 }
1241 1247
1242 1248
1243 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1249 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1244 // Record position before possible IC call. 1250 // Record position before possible IC call.
1245 SetSourcePosition(proxy->position()); 1251 SetSourcePosition(proxy->position());
1246 Variable* var = proxy->var(); 1252 Variable* var = proxy->var();
(...skipping 12 matching lines...) Expand all
1259 context()->Plug(v0); 1265 context()->Plug(v0);
1260 break; 1266 break;
1261 } 1267 }
1262 1268
1263 case Variable::PARAMETER: 1269 case Variable::PARAMETER:
1264 case Variable::LOCAL: 1270 case Variable::LOCAL:
1265 case Variable::CONTEXT: { 1271 case Variable::CONTEXT: {
1266 Comment cmnt(masm_, var->IsContextSlot() 1272 Comment cmnt(masm_, var->IsContextSlot()
1267 ? "Context variable" 1273 ? "Context variable"
1268 : "Stack variable"); 1274 : "Stack variable");
1269 if (var->mode() != Variable::LET && var->mode() != Variable::CONST) { 1275 if (var->mode() != LET && var->mode() != CONST) {
1270 context()->Plug(var); 1276 context()->Plug(var);
1271 } else { 1277 } else {
1272 // Let and const need a read barrier. 1278 // Let and const need a read barrier.
1273 GetVar(v0, var); 1279 GetVar(v0, var);
1274 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1280 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1275 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1281 __ subu(at, v0, at); // Sub as compare: at == 0 on eq.
1276 if (var->mode() == Variable::LET) { 1282 if (var->mode() == LET) {
1277 Label done; 1283 Label done;
1278 __ Branch(&done, ne, at, Operand(zero_reg)); 1284 __ Branch(&done, ne, at, Operand(zero_reg));
1279 __ li(a0, Operand(var->name())); 1285 __ li(a0, Operand(var->name()));
1280 __ push(a0); 1286 __ push(a0);
1281 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1287 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1282 __ bind(&done); 1288 __ bind(&done);
1283 } else { 1289 } else {
1284 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1290 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1285 __ movz(v0, a0, at); // Conditional move: Undefined if TheHole. 1291 __ movz(v0, a0, at); // Conditional move: Undefined if TheHole.
1286 } 1292 }
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 continue; 1512 continue;
1507 } 1513 }
1508 1514
1509 if (!result_saved) { 1515 if (!result_saved) {
1510 __ push(v0); 1516 __ push(v0);
1511 result_saved = true; 1517 result_saved = true;
1512 } 1518 }
1513 VisitForAccumulatorValue(subexpr); 1519 VisitForAccumulatorValue(subexpr);
1514 1520
1515 // Store the subexpression value in the array's elements. 1521 // Store the subexpression value in the array's elements.
1516 __ lw(a1, MemOperand(sp)); // Copy of array literal. 1522 __ lw(t6, MemOperand(sp)); // Copy of array literal.
1517 __ lw(a1, FieldMemOperand(a1, JSObject::kElementsOffset)); 1523 __ lw(a1, FieldMemOperand(t6, JSObject::kElementsOffset));
1518 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1524 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1519 __ sw(result_register(), FieldMemOperand(a1, offset)); 1525 __ sw(result_register(), FieldMemOperand(a1, offset));
1520 1526
1527 Label no_map_change;
1528 __ JumpIfSmi(result_register(), &no_map_change);
1521 // Update the write barrier for the array store with v0 as the scratch 1529 // Update the write barrier for the array store with v0 as the scratch
1522 // register. 1530 // register.
1523 __ RecordWriteField( 1531 __ RecordWriteField(
1524 a1, offset, result_register(), a2, kRAHasBeenSaved, kDontSaveFPRegs); 1532 a1, offset, result_register(), a2, kRAHasBeenSaved, kDontSaveFPRegs,
1533 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1534 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
1535 __ CheckFastSmiOnlyElements(a3, a2, &no_map_change);
1536 __ push(t6); // Copy of array literal.
1537 __ CallRuntime(Runtime::kNonSmiElementStored, 1);
1538 __ bind(&no_map_change);
1525 1539
1526 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1540 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1527 } 1541 }
1528 1542
1529 if (result_saved) { 1543 if (result_saved) {
1530 context()->PlugTOS(); 1544 context()->PlugTOS();
1531 } else { 1545 } else {
1532 context()->Plug(v0); 1546 context()->Plug(v0);
1533 } 1547 }
1534 } 1548 }
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 // scope. However, unlike var initializers, const initializers are 1880 // scope. However, unlike var initializers, const initializers are
1867 // able to drill a hole to that function context, even from inside a 1881 // able to drill a hole to that function context, even from inside a
1868 // 'with' context. We thus bypass the normal static scope lookup for 1882 // 'with' context. We thus bypass the normal static scope lookup for
1869 // var->IsContextSlot(). 1883 // var->IsContextSlot().
1870 __ push(v0); 1884 __ push(v0);
1871 __ li(a0, Operand(var->name())); 1885 __ li(a0, Operand(var->name()));
1872 __ Push(cp, a0); // Context and name. 1886 __ Push(cp, a0); // Context and name.
1873 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1887 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1874 } 1888 }
1875 1889
1876 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) { 1890 } else if (var->mode() == LET && op != Token::INIT_LET) {
1877 // Non-initializing assignment to let variable needs a write barrier. 1891 // Non-initializing assignment to let variable needs a write barrier.
1878 if (var->IsLookupSlot()) { 1892 if (var->IsLookupSlot()) {
1879 __ push(v0); // Value. 1893 __ push(v0); // Value.
1880 __ li(a1, Operand(var->name())); 1894 __ li(a1, Operand(var->name()));
1881 __ li(a0, Operand(Smi::FromInt(strict_mode_flag()))); 1895 __ li(a0, Operand(Smi::FromInt(strict_mode_flag())));
1882 __ Push(cp, a1, a0); // Context, name, strict mode. 1896 __ Push(cp, a1, a0); // Context, name, strict mode.
1883 __ CallRuntime(Runtime::kStoreContextSlot, 4); 1897 __ CallRuntime(Runtime::kStoreContextSlot, 4);
1884 } else { 1898 } else {
1885 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 1899 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
1886 Label assign; 1900 Label assign;
1887 MemOperand location = VarOperand(var, a1); 1901 MemOperand location = VarOperand(var, a1);
1888 __ lw(a3, location); 1902 __ lw(a3, location);
1889 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 1903 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
1890 __ Branch(&assign, ne, a3, Operand(t0)); 1904 __ Branch(&assign, ne, a3, Operand(t0));
1891 __ li(a3, Operand(var->name())); 1905 __ li(a3, Operand(var->name()));
1892 __ push(a3); 1906 __ push(a3);
1893 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1907 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1894 // Perform the assignment. 1908 // Perform the assignment.
1895 __ bind(&assign); 1909 __ bind(&assign);
1896 __ sw(result_register(), location); 1910 __ sw(result_register(), location);
1897 if (var->IsContextSlot()) { 1911 if (var->IsContextSlot()) {
1898 // RecordWrite may destroy all its register arguments. 1912 // RecordWrite may destroy all its register arguments.
1899 __ mov(a3, result_register()); 1913 __ mov(a3, result_register());
1900 int offset = Context::SlotOffset(var->index()); 1914 int offset = Context::SlotOffset(var->index());
1901 __ RecordWriteContextSlot( 1915 __ RecordWriteContextSlot(
1902 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); 1916 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
1903 } 1917 }
1904 } 1918 }
1905 1919
1906 } else if (var->mode() != Variable::CONST) { 1920 } else if (var->mode() != CONST) {
1907 // Assignment to var or initializing assignment to let. 1921 // Assignment to var or initializing assignment to let.
1908 if (var->IsStackAllocated() || var->IsContextSlot()) { 1922 if (var->IsStackAllocated() || var->IsContextSlot()) {
1909 MemOperand location = VarOperand(var, a1); 1923 MemOperand location = VarOperand(var, a1);
1910 if (FLAG_debug_code && op == Token::INIT_LET) { 1924 if (FLAG_debug_code && op == Token::INIT_LET) {
1911 // Check for an uninitialized let binding. 1925 // Check for an uninitialized let binding.
1912 __ lw(a2, location); 1926 __ lw(a2, location);
1913 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 1927 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
1914 __ Check(eq, "Let binding re-initialization.", a2, Operand(t0)); 1928 __ Check(eq, "Let binding re-initialization.", a2, Operand(t0));
1915 } 1929 }
1916 // Perform the assignment. 1930 // Perform the assignment.
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
2187 for (int i = 0; i < arg_count; i++) { 2201 for (int i = 0; i < arg_count; i++) {
2188 VisitForStackValue(args->at(i)); 2202 VisitForStackValue(args->at(i));
2189 } 2203 }
2190 2204
2191 // If we know that eval can only be shadowed by eval-introduced 2205 // If we know that eval can only be shadowed by eval-introduced
2192 // variables we attempt to load the global eval function directly 2206 // variables we attempt to load the global eval function directly
2193 // in generated code. If we succeed, there is no need to perform a 2207 // in generated code. If we succeed, there is no need to perform a
2194 // context lookup in the runtime system. 2208 // context lookup in the runtime system.
2195 Label done; 2209 Label done;
2196 Variable* var = proxy->var(); 2210 Variable* var = proxy->var();
2197 if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) { 2211 if (!var->IsUnallocated() && var->mode() == DYNAMIC_GLOBAL) {
2198 Label slow; 2212 Label slow;
2199 EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow); 2213 EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
2200 // Push the function and resolve eval. 2214 // Push the function and resolve eval.
2201 __ push(v0); 2215 __ push(v0);
2202 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count); 2216 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
2203 __ jmp(&done); 2217 __ jmp(&done);
2204 __ bind(&slow); 2218 __ bind(&slow);
2205 } 2219 }
2206 2220
2207 // Push a copy of the function (found below the arguments) and 2221 // Push a copy of the function (found below the arguments) and
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
2688 ASSERT(args->length() == 1); 2702 ASSERT(args->length() == 1);
2689 Label done, null, function, non_function_constructor; 2703 Label done, null, function, non_function_constructor;
2690 2704
2691 VisitForAccumulatorValue(args->at(0)); 2705 VisitForAccumulatorValue(args->at(0));
2692 2706
2693 // If the object is a smi, we return null. 2707 // If the object is a smi, we return null.
2694 __ JumpIfSmi(v0, &null); 2708 __ JumpIfSmi(v0, &null);
2695 2709
2696 // Check that the object is a JS object but take special care of JS 2710 // Check that the object is a JS object but take special care of JS
2697 // functions to make sure they have 'Function' as their class. 2711 // functions to make sure they have 'Function' as their class.
2712 // Assume that there are only two callable types, and one of them is at
2713 // either end of the type range for JS object types. Saves extra comparisons.
2714 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2698 __ GetObjectType(v0, v0, a1); // Map is now in v0. 2715 __ GetObjectType(v0, v0, a1); // Map is now in v0.
2699 __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); 2716 __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
2700 2717
2701 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and 2718 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2702 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after 2719 FIRST_SPEC_OBJECT_TYPE + 1);
2703 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. 2720 __ Branch(&function, eq, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
2704 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
2705 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
2706 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
2707 __ Branch(&function, ge, a1, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE));
2708 2721
2709 // Check if the constructor in the map is a function. 2722 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2723 LAST_SPEC_OBJECT_TYPE - 1);
2724 __ Branch(&function, eq, a1, Operand(LAST_SPEC_OBJECT_TYPE));
2725 // Assume that there is no larger type.
2726 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
2727
2728 // Check if the constructor in the map is a JS function.
2710 __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset)); 2729 __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset));
2711 __ GetObjectType(v0, a1, a1); 2730 __ GetObjectType(v0, a1, a1);
2712 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE)); 2731 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE));
2713 2732
2714 // v0 now contains the constructor function. Grab the 2733 // v0 now contains the constructor function. Grab the
2715 // instance class name from there. 2734 // instance class name from there.
2716 __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset)); 2735 __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
2717 __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset)); 2736 __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset));
2718 __ Branch(&done); 2737 __ Branch(&done);
2719 2738
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
3186 1 << MemoryChunk::SCAN_ON_SCAVENGE, 3205 1 << MemoryChunk::SCAN_ON_SCAVENGE,
3187 ne, 3206 ne,
3188 &no_remembered_set); 3207 &no_remembered_set);
3189 // Possible optimization: do a check that both values are Smis 3208 // Possible optimization: do a check that both values are Smis
3190 // (or them and test against Smi mask). 3209 // (or them and test against Smi mask).
3191 3210
3192 // We are swapping two objects in an array and the incremental marker never 3211 // We are swapping two objects in an array and the incremental marker never
3193 // pauses in the middle of scanning a single object. Therefore the 3212 // pauses in the middle of scanning a single object. Therefore the
3194 // incremental marker is not disturbed, so we don't need to call the 3213 // incremental marker is not disturbed, so we don't need to call the
3195 // RecordWrite stub that notifies the incremental marker. 3214 // RecordWrite stub that notifies the incremental marker.
3196 __ RememberedSetHelper( 3215 __ RememberedSetHelper(elements,
3197 index1, scratch2, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); 3216 index1,
3198 __ RememberedSetHelper( 3217 scratch2,
3199 index2, scratch2, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); 3218 kDontSaveFPRegs,
3219 MacroAssembler::kFallThroughAtEnd);
3220 __ RememberedSetHelper(elements,
3221 index2,
3222 scratch2,
3223 kDontSaveFPRegs,
3224 MacroAssembler::kFallThroughAtEnd);
3200 3225
3201 __ bind(&no_remembered_set); 3226 __ bind(&no_remembered_set);
3202 // We are done. Drop elements from the stack, and return undefined. 3227 // We are done. Drop elements from the stack, and return undefined.
3203 __ Drop(3); 3228 __ Drop(3);
3204 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 3229 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
3205 __ jmp(&done); 3230 __ jmp(&done);
3206 3231
3207 __ bind(&slow_case); 3232 __ bind(&slow_case);
3208 __ CallRuntime(Runtime::kSwapElements, 3); 3233 __ CallRuntime(Runtime::kSwapElements, 3);
3209 3234
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
3996 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 4021 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
3997 __ Branch(if_true, eq, v0, Operand(at)); 4022 __ Branch(if_true, eq, v0, Operand(at));
3998 __ JumpIfSmi(v0, if_false); 4023 __ JumpIfSmi(v0, if_false);
3999 // Check for undetectable objects => true. 4024 // Check for undetectable objects => true.
4000 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4025 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4001 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); 4026 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
4002 __ And(a1, a1, Operand(1 << Map::kIsUndetectable)); 4027 __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
4003 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through); 4028 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
4004 } else if (check->Equals(isolate()->heap()->function_symbol())) { 4029 } else if (check->Equals(isolate()->heap()->function_symbol())) {
4005 __ JumpIfSmi(v0, if_false); 4030 __ JumpIfSmi(v0, if_false);
4006 __ GetObjectType(v0, a1, v0); // Leave map in a1. 4031 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4007 Split(ge, v0, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE), 4032 __ GetObjectType(v0, v0, a1);
4008 if_true, if_false, fall_through); 4033 __ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE));
4009 4034 Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE),
4035 if_true, if_false, fall_through);
4010 } else if (check->Equals(isolate()->heap()->object_symbol())) { 4036 } else if (check->Equals(isolate()->heap()->object_symbol())) {
4011 __ JumpIfSmi(v0, if_false); 4037 __ JumpIfSmi(v0, if_false);
4012 if (!FLAG_harmony_typeof) { 4038 if (!FLAG_harmony_typeof) {
4013 __ LoadRoot(at, Heap::kNullValueRootIndex); 4039 __ LoadRoot(at, Heap::kNullValueRootIndex);
4014 __ Branch(if_true, eq, v0, Operand(at)); 4040 __ Branch(if_true, eq, v0, Operand(at));
4015 } 4041 }
4016 // Check for JS objects => true. 4042 // Check for JS objects => true.
4017 __ GetObjectType(v0, v0, a1); 4043 __ GetObjectType(v0, v0, a1);
4018 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 4044 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
4019 __ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset)); 4045 __ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset));
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
4271 *context_length = 0; 4297 *context_length = 0;
4272 return previous_; 4298 return previous_;
4273 } 4299 }
4274 4300
4275 4301
4276 #undef __ 4302 #undef __
4277 4303
4278 } } // namespace v8::internal 4304 } } // namespace v8::internal
4279 4305
4280 #endif // V8_TARGET_ARCH_MIPS 4306 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/code-stubs-mips.cc ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698