| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1825 target->ReplaceCode(shared->code()); | 1825 target->ReplaceCode(shared->code()); |
| 1826 target->shared()->set_scope_info(shared->scope_info()); | 1826 target->shared()->set_scope_info(shared->scope_info()); |
| 1827 target->shared()->set_length(shared->length()); | 1827 target->shared()->set_length(shared->length()); |
| 1828 target->shared()->set_formal_parameter_count( | 1828 target->shared()->set_formal_parameter_count( |
| 1829 shared->formal_parameter_count()); | 1829 shared->formal_parameter_count()); |
| 1830 // Set the source code of the target function to undefined. | 1830 // Set the source code of the target function to undefined. |
| 1831 // SetCode is only used for built-in constructors like String, | 1831 // SetCode is only used for built-in constructors like String, |
| 1832 // Array, and Object, and some web code | 1832 // Array, and Object, and some web code |
| 1833 // doesn't like seeing source code for constructors. | 1833 // doesn't like seeing source code for constructors. |
| 1834 target->shared()->set_script(isolate->heap()->undefined_value()); | 1834 target->shared()->set_script(isolate->heap()->undefined_value()); |
| 1835 target->shared()->code()->set_optimizable(false); |
| 1835 // Clear the optimization hints related to the compiled code as these are no | 1836 // Clear the optimization hints related to the compiled code as these are no |
| 1836 // longer valid when the code is overwritten. | 1837 // longer valid when the code is overwritten. |
| 1837 target->shared()->ClearThisPropertyAssignmentsInfo(); | 1838 target->shared()->ClearThisPropertyAssignmentsInfo(); |
| 1838 context = Handle<Context>(fun->context()); | 1839 context = Handle<Context>(fun->context()); |
| 1839 | 1840 |
| 1840 // Make sure we get a fresh copy of the literal vector to avoid | 1841 // Make sure we get a fresh copy of the literal vector to avoid |
| 1841 // cross context contamination. | 1842 // cross context contamination. |
| 1842 int number_of_literals = fun->NumberOfLiterals(); | 1843 int number_of_literals = fun->NumberOfLiterals(); |
| 1843 Handle<FixedArray> literals = | 1844 Handle<FixedArray> literals = |
| 1844 isolate->factory()->NewFixedArray(number_of_literals, TENURED); | 1845 isolate->factory()->NewFixedArray(number_of_literals, TENURED); |
| (...skipping 2974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4819 return HEAP->AllocateRawTwoByteString(length); | 4820 return HEAP->AllocateRawTwoByteString(length); |
| 4820 } | 4821 } |
| 4821 | 4822 |
| 4822 | 4823 |
| 4823 template <> | 4824 template <> |
| 4824 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { | 4825 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
| 4825 return HEAP->AllocateRawAsciiString(length); | 4826 return HEAP->AllocateRawAsciiString(length); |
| 4826 } | 4827 } |
| 4827 | 4828 |
| 4828 | 4829 |
| 4829 template <typename Char, typename StringType> | 4830 template <typename Char, typename StringType, bool comma> |
| 4830 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { | 4831 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { |
| 4831 int length = characters.length(); | 4832 int length = characters.length(); |
| 4832 const Char* read_cursor = characters.start(); | 4833 const Char* read_cursor = characters.start(); |
| 4833 const Char* end = read_cursor + length; | 4834 const Char* end = read_cursor + length; |
| 4834 const int kSpaceForQuotes = 2; | 4835 const int kSpaceForQuotes = 2 + (comma ? 1 :0); |
| 4835 int quoted_length = kSpaceForQuotes; | 4836 int quoted_length = kSpaceForQuotes; |
| 4836 while (read_cursor < end) { | 4837 while (read_cursor < end) { |
| 4837 Char c = *(read_cursor++); | 4838 Char c = *(read_cursor++); |
| 4838 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4839 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4839 quoted_length++; | 4840 quoted_length++; |
| 4840 } else { | 4841 } else { |
| 4841 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; | 4842 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4842 } | 4843 } |
| 4843 } | 4844 } |
| 4844 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); | 4845 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
| 4845 Object* new_object; | 4846 Object* new_object; |
| 4846 if (!new_alloc->ToObject(&new_object)) { | 4847 if (!new_alloc->ToObject(&new_object)) { |
| 4847 return new_alloc; | 4848 return new_alloc; |
| 4848 } | 4849 } |
| 4849 StringType* new_string = StringType::cast(new_object); | 4850 StringType* new_string = StringType::cast(new_object); |
| 4850 | 4851 |
| 4851 Char* write_cursor = reinterpret_cast<Char*>( | 4852 Char* write_cursor = reinterpret_cast<Char*>( |
| 4852 new_string->address() + SeqAsciiString::kHeaderSize); | 4853 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4854 if (comma) *(write_cursor++) = ','; |
| 4853 *(write_cursor++) = '"'; | 4855 *(write_cursor++) = '"'; |
| 4854 | 4856 |
| 4855 read_cursor = characters.start(); | 4857 read_cursor = characters.start(); |
| 4856 while (read_cursor < end) { | 4858 while (read_cursor < end) { |
| 4857 Char c = *(read_cursor++); | 4859 Char c = *(read_cursor++); |
| 4858 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4860 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4859 *(write_cursor++) = c; | 4861 *(write_cursor++) = c; |
| 4860 } else { | 4862 } else { |
| 4861 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 4863 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4862 const char* replacement = JsonQuotes + | 4864 const char* replacement = JsonQuotes + |
| 4863 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; | 4865 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
| 4864 for (int i = 0; i < len; i++) { | 4866 for (int i = 0; i < len; i++) { |
| 4865 *write_cursor++ = *replacement++; | 4867 *write_cursor++ = *replacement++; |
| 4866 } | 4868 } |
| 4867 } | 4869 } |
| 4868 } | 4870 } |
| 4869 *(write_cursor++) = '"'; | 4871 *(write_cursor++) = '"'; |
| 4870 return new_string; | 4872 return new_string; |
| 4871 } | 4873 } |
| 4872 | 4874 |
| 4873 | 4875 |
| 4874 template <typename Char, typename StringType> | 4876 template <typename Char, typename StringType, bool comma> |
| 4875 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { | 4877 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
| 4876 int length = characters.length(); | 4878 int length = characters.length(); |
| 4877 COUNTERS->quote_json_char_count()->Increment(length); | 4879 COUNTERS->quote_json_char_count()->Increment(length); |
| 4878 const int kSpaceForQuotes = 2; | 4880 const int kSpaceForQuotes = 2 + (comma ? 1 :0); |
| 4879 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 4881 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 4880 if (worst_case_length > kMaxGuaranteedNewSpaceString) { | 4882 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
| 4881 return SlowQuoteJsonString<Char, StringType>(characters); | 4883 return SlowQuoteJsonString<Char, StringType, comma>(characters); |
| 4882 } | 4884 } |
| 4883 | 4885 |
| 4884 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); | 4886 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); |
| 4885 Object* new_object; | 4887 Object* new_object; |
| 4886 if (!new_alloc->ToObject(&new_object)) { | 4888 if (!new_alloc->ToObject(&new_object)) { |
| 4887 return new_alloc; | 4889 return new_alloc; |
| 4888 } | 4890 } |
| 4889 if (!HEAP->new_space()->Contains(new_object)) { | 4891 if (!HEAP->new_space()->Contains(new_object)) { |
| 4890 // Even if our string is small enough to fit in new space we still have to | 4892 // Even if our string is small enough to fit in new space we still have to |
| 4891 // handle it being allocated in old space as may happen in the third | 4893 // handle it being allocated in old space as may happen in the third |
| 4892 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | 4894 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
| 4893 // CEntryStub::GenerateCore. | 4895 // CEntryStub::GenerateCore. |
| 4894 return SlowQuoteJsonString<Char, StringType>(characters); | 4896 return SlowQuoteJsonString<Char, StringType, comma>(characters); |
| 4895 } | 4897 } |
| 4896 StringType* new_string = StringType::cast(new_object); | 4898 StringType* new_string = StringType::cast(new_object); |
| 4897 ASSERT(HEAP->new_space()->Contains(new_string)); | 4899 ASSERT(HEAP->new_space()->Contains(new_string)); |
| 4898 | 4900 |
| 4899 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4901 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 4900 Char* write_cursor = reinterpret_cast<Char*>( | 4902 Char* write_cursor = reinterpret_cast<Char*>( |
| 4901 new_string->address() + SeqAsciiString::kHeaderSize); | 4903 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4904 if (comma) *(write_cursor++) = ','; |
| 4902 *(write_cursor++) = '"'; | 4905 *(write_cursor++) = '"'; |
| 4903 | 4906 |
| 4904 const Char* read_cursor = characters.start(); | 4907 const Char* read_cursor = characters.start(); |
| 4905 const Char* end = read_cursor + length; | 4908 const Char* end = read_cursor + length; |
| 4906 while (read_cursor < end) { | 4909 while (read_cursor < end) { |
| 4907 Char c = *(read_cursor++); | 4910 Char c = *(read_cursor++); |
| 4908 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4911 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4909 *(write_cursor++) = c; | 4912 *(write_cursor++) = c; |
| 4910 } else { | 4913 } else { |
| 4911 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 4914 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4943 if (!str->IsFlat()) { | 4946 if (!str->IsFlat()) { |
| 4944 MaybeObject* try_flatten = str->TryFlatten(); | 4947 MaybeObject* try_flatten = str->TryFlatten(); |
| 4945 Object* flat; | 4948 Object* flat; |
| 4946 if (!try_flatten->ToObject(&flat)) { | 4949 if (!try_flatten->ToObject(&flat)) { |
| 4947 return try_flatten; | 4950 return try_flatten; |
| 4948 } | 4951 } |
| 4949 str = String::cast(flat); | 4952 str = String::cast(flat); |
| 4950 ASSERT(str->IsFlat()); | 4953 ASSERT(str->IsFlat()); |
| 4951 } | 4954 } |
| 4952 if (str->IsTwoByteRepresentation()) { | 4955 if (str->IsTwoByteRepresentation()) { |
| 4953 return QuoteJsonString<uc16, SeqTwoByteString>(str->ToUC16Vector()); | 4956 return QuoteJsonString<uc16, SeqTwoByteString, false>(str->ToUC16Vector()); |
| 4954 } else { | 4957 } else { |
| 4955 return QuoteJsonString<char, SeqAsciiString>(str->ToAsciiVector()); | 4958 return QuoteJsonString<char, SeqAsciiString, false>(str->ToAsciiVector()); |
| 4956 } | 4959 } |
| 4957 } | 4960 } |
| 4958 | 4961 |
| 4959 | 4962 |
| 4963 static MaybeObject* Runtime_QuoteJSONStringComma(RUNTIME_CALLING_CONVENTION) { |
| 4964 RUNTIME_GET_ISOLATE; |
| 4965 NoHandleAllocation ha; |
| 4966 CONVERT_CHECKED(String, str, args[0]); |
| 4967 if (!str->IsFlat()) { |
| 4968 MaybeObject* try_flatten = str->TryFlatten(); |
| 4969 Object* flat; |
| 4970 if (!try_flatten->ToObject(&flat)) { |
| 4971 return try_flatten; |
| 4972 } |
| 4973 str = String::cast(flat); |
| 4974 ASSERT(str->IsFlat()); |
| 4975 } |
| 4976 if (str->IsTwoByteRepresentation()) { |
| 4977 return QuoteJsonString<uc16, SeqTwoByteString, true>(str->ToUC16Vector()); |
| 4978 } else { |
| 4979 return QuoteJsonString<char, SeqAsciiString, true>(str->ToAsciiVector()); |
| 4980 } |
| 4981 } |
| 4960 | 4982 |
| 4961 static MaybeObject* Runtime_StringParseInt(RUNTIME_CALLING_CONVENTION) { | 4983 static MaybeObject* Runtime_StringParseInt(RUNTIME_CALLING_CONVENTION) { |
| 4962 RUNTIME_GET_ISOLATE; | 4984 RUNTIME_GET_ISOLATE; |
| 4963 NoHandleAllocation ha; | 4985 NoHandleAllocation ha; |
| 4964 | 4986 |
| 4965 CONVERT_CHECKED(String, s, args[0]); | 4987 CONVERT_CHECKED(String, s, args[0]); |
| 4966 CONVERT_SMI_CHECKED(radix, args[1]); | 4988 CONVERT_SMI_CHECKED(radix, args[1]); |
| 4967 | 4989 |
| 4968 s->TryFlatten(); | 4990 s->TryFlatten(); |
| 4969 | 4991 |
| (...skipping 2031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7001 | 7023 |
| 7002 static MaybeObject* Runtime_LazyRecompile(RUNTIME_CALLING_CONVENTION) { | 7024 static MaybeObject* Runtime_LazyRecompile(RUNTIME_CALLING_CONVENTION) { |
| 7003 RUNTIME_GET_ISOLATE; | 7025 RUNTIME_GET_ISOLATE; |
| 7004 HandleScope scope(isolate); | 7026 HandleScope scope(isolate); |
| 7005 ASSERT(args.length() == 1); | 7027 ASSERT(args.length() == 1); |
| 7006 Handle<JSFunction> function = args.at<JSFunction>(0); | 7028 Handle<JSFunction> function = args.at<JSFunction>(0); |
| 7007 // If the function is not optimizable or debugger is active continue using the | 7029 // If the function is not optimizable or debugger is active continue using the |
| 7008 // code from the full compiler. | 7030 // code from the full compiler. |
| 7009 if (!function->shared()->code()->optimizable() || | 7031 if (!function->shared()->code()->optimizable() || |
| 7010 isolate->debug()->has_break_points()) { | 7032 isolate->debug()->has_break_points()) { |
| 7033 if (FLAG_trace_opt) { |
| 7034 PrintF("[failed to optimize "); |
| 7035 function->PrintName(); |
| 7036 PrintF(": is code optimizable: %s, is debugger enabled: %s]\n", |
| 7037 function->shared()->code()->optimizable() ? "T" : "F", |
| 7038 isolate->debug()->has_break_points() ? "T" : "F"); |
| 7039 } |
| 7011 function->ReplaceCode(function->shared()->code()); | 7040 function->ReplaceCode(function->shared()->code()); |
| 7012 return function->code(); | 7041 return function->code(); |
| 7013 } | 7042 } |
| 7014 if (CompileOptimized(function, AstNode::kNoNumber)) { | 7043 if (CompileOptimized(function, AstNode::kNoNumber)) { |
| 7015 return function->code(); | 7044 return function->code(); |
| 7016 } | 7045 } |
| 7046 if (FLAG_trace_opt) { |
| 7047 PrintF("[failed to optimize "); |
| 7048 function->PrintName(); |
| 7049 PrintF(": optimized compilation failed]\n"); |
| 7050 } |
| 7017 function->ReplaceCode(function->shared()->code()); | 7051 function->ReplaceCode(function->shared()->code()); |
| 7018 return Failure::Exception(); | 7052 return Failure::Exception(); |
| 7019 } | 7053 } |
| 7020 | 7054 |
| 7021 | 7055 |
| 7022 static MaybeObject* Runtime_NotifyDeoptimized(RUNTIME_CALLING_CONVENTION) { | 7056 static MaybeObject* Runtime_NotifyDeoptimized(RUNTIME_CALLING_CONVENTION) { |
| 7023 RUNTIME_GET_ISOLATE; | 7057 RUNTIME_GET_ISOLATE; |
| 7024 HandleScope scope(isolate); | 7058 HandleScope scope(isolate); |
| 7025 ASSERT(args.length() == 1); | 7059 ASSERT(args.length() == 1); |
| 7026 RUNTIME_ASSERT(args[0]->IsSmi()); | 7060 RUNTIME_ASSERT(args[0]->IsSmi()); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7202 // Revert to the original stack checks in the original unoptimized code. | 7236 // Revert to the original stack checks in the original unoptimized code. |
| 7203 if (FLAG_trace_osr) { | 7237 if (FLAG_trace_osr) { |
| 7204 PrintF("[restoring original stack checks in "); | 7238 PrintF("[restoring original stack checks in "); |
| 7205 function->PrintName(); | 7239 function->PrintName(); |
| 7206 PrintF("]\n"); | 7240 PrintF("]\n"); |
| 7207 } | 7241 } |
| 7208 StackCheckStub check_stub; | 7242 StackCheckStub check_stub; |
| 7209 Handle<Code> check_code = check_stub.GetCode(); | 7243 Handle<Code> check_code = check_stub.GetCode(); |
| 7210 Handle<Code> replacement_code( | 7244 Handle<Code> replacement_code( |
| 7211 isolate->builtins()->builtin(Builtins::OnStackReplacement)); | 7245 isolate->builtins()->builtin(Builtins::OnStackReplacement)); |
| 7212 // Iterate the unoptimized code and revert all the patched stack checks. | 7246 Deoptimizer::RevertStackCheckCode(*unoptimized, |
| 7213 for (RelocIterator it(*unoptimized, RelocInfo::kCodeTargetMask); | 7247 *check_code, |
| 7214 !it.done(); | 7248 *replacement_code); |
| 7215 it.next()) { | |
| 7216 RelocInfo* rinfo = it.rinfo(); | |
| 7217 if (rinfo->target_address() == replacement_code->entry()) { | |
| 7218 Deoptimizer::RevertStackCheckCode(rinfo, *check_code); | |
| 7219 } | |
| 7220 } | |
| 7221 | 7249 |
| 7222 // Allow OSR only at nesting level zero again. | 7250 // Allow OSR only at nesting level zero again. |
| 7223 unoptimized->set_allow_osr_at_loop_nesting_level(0); | 7251 unoptimized->set_allow_osr_at_loop_nesting_level(0); |
| 7224 | 7252 |
| 7225 // If the optimization attempt succeeded, return the AST id tagged as a | 7253 // If the optimization attempt succeeded, return the AST id tagged as a |
| 7226 // smi. This tells the builtin that we need to translate the unoptimized | 7254 // smi. This tells the builtin that we need to translate the unoptimized |
| 7227 // frame to an optimized one. | 7255 // frame to an optimized one. |
| 7228 if (succeeded) { | 7256 if (succeeded) { |
| 7229 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | 7257 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
| 7230 return Smi::FromInt(ast_id); | 7258 return Smi::FromInt(ast_id); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7313 | 7341 |
| 7314 | 7342 |
| 7315 static MaybeObject* Runtime_PushCatchContext(RUNTIME_CALLING_CONVENTION) { | 7343 static MaybeObject* Runtime_PushCatchContext(RUNTIME_CALLING_CONVENTION) { |
| 7316 RUNTIME_GET_ISOLATE; | 7344 RUNTIME_GET_ISOLATE; |
| 7317 NoHandleAllocation ha; | 7345 NoHandleAllocation ha; |
| 7318 ASSERT(args.length() == 1); | 7346 ASSERT(args.length() == 1); |
| 7319 return PushContextHelper(isolate, args[0], true); | 7347 return PushContextHelper(isolate, args[0], true); |
| 7320 } | 7348 } |
| 7321 | 7349 |
| 7322 | 7350 |
| 7323 static MaybeObject* Runtime_LookupContext(RUNTIME_CALLING_CONVENTION) { | 7351 static MaybeObject* Runtime_DeleteContextSlot(RUNTIME_CALLING_CONVENTION) { |
| 7324 RUNTIME_GET_ISOLATE; | 7352 RUNTIME_GET_ISOLATE; |
| 7325 HandleScope scope(isolate); | 7353 HandleScope scope(isolate); |
| 7326 ASSERT(args.length() == 2); | 7354 ASSERT(args.length() == 2); |
| 7327 | 7355 |
| 7328 CONVERT_ARG_CHECKED(Context, context, 0); | 7356 CONVERT_ARG_CHECKED(Context, context, 0); |
| 7329 CONVERT_ARG_CHECKED(String, name, 1); | 7357 CONVERT_ARG_CHECKED(String, name, 1); |
| 7330 | 7358 |
| 7331 int index; | 7359 int index; |
| 7332 PropertyAttributes attributes; | 7360 PropertyAttributes attributes; |
| 7333 ContextLookupFlags flags = FOLLOW_CHAINS; | 7361 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7334 Handle<Object> holder = | 7362 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7335 context->Lookup(name, flags, &index, &attributes); | |
| 7336 | 7363 |
| 7337 if (index < 0 && !holder.is_null()) { | 7364 // If the slot was not found the result is true. |
| 7338 ASSERT(holder->IsJSObject()); | 7365 if (holder.is_null()) { |
| 7339 return *holder; | 7366 return isolate->heap()->true_value(); |
| 7340 } | 7367 } |
| 7341 | 7368 |
| 7342 // No intermediate context found. Use global object by default. | 7369 // If the slot was found in a context, it should be DONT_DELETE. |
| 7343 return isolate->context()->global(); | 7370 if (holder->IsContext()) { |
| 7371 return isolate->heap()->false_value(); |
| 7372 } |
| 7373 |
| 7374 // The slot was found in a JSObject, either a context extension object, |
| 7375 // the global object, or an arguments object. Try to delete it |
| 7376 // (respecting DONT_DELETE). For consistency with V8's usual behavior, |
| 7377 // which allows deleting all parameters in functions that mention |
| 7378 // 'arguments', we do this even for the case of slots found on an |
| 7379 // arguments object. The slot was found on an arguments object if the |
| 7380 // index is non-negative. |
| 7381 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 7382 if (index >= 0) { |
| 7383 return object->DeleteElement(index, JSObject::NORMAL_DELETION); |
| 7384 } else { |
| 7385 return object->DeleteProperty(*name, JSObject::NORMAL_DELETION); |
| 7386 } |
| 7344 } | 7387 } |
| 7345 | 7388 |
| 7346 | 7389 |
| 7347 // A mechanism to return a pair of Object pointers in registers (if possible). | 7390 // A mechanism to return a pair of Object pointers in registers (if possible). |
| 7348 // How this is achieved is calling convention-dependent. | 7391 // How this is achieved is calling convention-dependent. |
| 7349 // All currently supported x86 compiles uses calling conventions that are cdecl | 7392 // All currently supported x86 compiles uses calling conventions that are cdecl |
| 7350 // variants where a 64-bit value is returned in two 32-bit registers | 7393 // variants where a 64-bit value is returned in two 32-bit registers |
| 7351 // (edx:eax on ia32, r1:r0 on ARM). | 7394 // (edx:eax on ia32, r1:r0 on ARM). |
| 7352 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. | 7395 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. |
| 7353 // In Win64 calling convention, a struct of two pointers is returned in memory, | 7396 // In Win64 calling convention, a struct of two pointers is returned in memory, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7410 | 7453 |
| 7411 if (!args[0]->IsContext() || !args[1]->IsString()) { | 7454 if (!args[0]->IsContext() || !args[1]->IsString()) { |
| 7412 return MakePair(isolate->ThrowIllegalOperation(), NULL); | 7455 return MakePair(isolate->ThrowIllegalOperation(), NULL); |
| 7413 } | 7456 } |
| 7414 Handle<Context> context = args.at<Context>(0); | 7457 Handle<Context> context = args.at<Context>(0); |
| 7415 Handle<String> name = args.at<String>(1); | 7458 Handle<String> name = args.at<String>(1); |
| 7416 | 7459 |
| 7417 int index; | 7460 int index; |
| 7418 PropertyAttributes attributes; | 7461 PropertyAttributes attributes; |
| 7419 ContextLookupFlags flags = FOLLOW_CHAINS; | 7462 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7420 Handle<Object> holder = | 7463 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7421 context->Lookup(name, flags, &index, &attributes); | |
| 7422 | 7464 |
| 7423 // If the index is non-negative, the slot has been found in a local | 7465 // If the index is non-negative, the slot has been found in a local |
| 7424 // variable or a parameter. Read it from the context object or the | 7466 // variable or a parameter. Read it from the context object or the |
| 7425 // arguments object. | 7467 // arguments object. |
| 7426 if (index >= 0) { | 7468 if (index >= 0) { |
| 7427 // If the "property" we were looking for is a local variable or an | 7469 // If the "property" we were looking for is a local variable or an |
| 7428 // argument in a context, the receiver is the global object; see | 7470 // argument in a context, the receiver is the global object; see |
| 7429 // ECMA-262, 3rd., 10.1.6 and 10.2.3. | 7471 // ECMA-262, 3rd., 10.1.6 and 10.2.3. |
| 7430 JSObject* receiver = | 7472 JSObject* receiver = |
| 7431 isolate->context()->global()->global_receiver(); | 7473 isolate->context()->global()->global_receiver(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7485 HandleScope scope(isolate); | 7527 HandleScope scope(isolate); |
| 7486 ASSERT(args.length() == 3); | 7528 ASSERT(args.length() == 3); |
| 7487 | 7529 |
| 7488 Handle<Object> value(args[0], isolate); | 7530 Handle<Object> value(args[0], isolate); |
| 7489 CONVERT_ARG_CHECKED(Context, context, 1); | 7531 CONVERT_ARG_CHECKED(Context, context, 1); |
| 7490 CONVERT_ARG_CHECKED(String, name, 2); | 7532 CONVERT_ARG_CHECKED(String, name, 2); |
| 7491 | 7533 |
| 7492 int index; | 7534 int index; |
| 7493 PropertyAttributes attributes; | 7535 PropertyAttributes attributes; |
| 7494 ContextLookupFlags flags = FOLLOW_CHAINS; | 7536 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7495 Handle<Object> holder = | 7537 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7496 context->Lookup(name, flags, &index, &attributes); | |
| 7497 | 7538 |
| 7498 if (index >= 0) { | 7539 if (index >= 0) { |
| 7499 if (holder->IsContext()) { | 7540 if (holder->IsContext()) { |
| 7500 // Ignore if read_only variable. | 7541 // Ignore if read_only variable. |
| 7501 if ((attributes & READ_ONLY) == 0) { | 7542 if ((attributes & READ_ONLY) == 0) { |
| 7502 Handle<Context>::cast(holder)->set(index, *value); | 7543 Handle<Context>::cast(holder)->set(index, *value); |
| 7503 } | 7544 } |
| 7504 } else { | 7545 } else { |
| 7505 ASSERT((attributes & READ_ONLY) == 0); | 7546 ASSERT((attributes & READ_ONLY) == 0); |
| 7506 Handle<JSObject>::cast(holder)->SetElement(index, *value)-> | 7547 Handle<JSObject>::cast(holder)->SetElement(index, *value)-> |
| (...skipping 3586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11093 ASSERT(args.length() == 2); | 11134 ASSERT(args.length() == 2); |
| 11094 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + | 11135 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + |
| 11095 Smi::cast(args[1])->value()); | 11136 Smi::cast(args[1])->value()); |
| 11096 isolate->PrintStack(); | 11137 isolate->PrintStack(); |
| 11097 OS::Abort(); | 11138 OS::Abort(); |
| 11098 UNREACHABLE(); | 11139 UNREACHABLE(); |
| 11099 return NULL; | 11140 return NULL; |
| 11100 } | 11141 } |
| 11101 | 11142 |
| 11102 | 11143 |
| 11103 MUST_USE_RESULT static MaybeObject* CacheMiss(Isolate* isolate, | |
| 11104 FixedArray* cache_obj, | |
| 11105 int index, | |
| 11106 Object* key_obj) { | |
| 11107 ASSERT(index % 2 == 0); // index of the key | |
| 11108 ASSERT(index >= JSFunctionResultCache::kEntriesIndex); | |
| 11109 ASSERT(index < cache_obj->length()); | |
| 11110 | |
| 11111 HandleScope scope(isolate); | |
| 11112 | |
| 11113 Handle<FixedArray> cache(cache_obj); | |
| 11114 Handle<Object> key(key_obj, isolate); | |
| 11115 Handle<JSFunction> factory(JSFunction::cast( | |
| 11116 cache->get(JSFunctionResultCache::kFactoryIndex))); | |
| 11117 // TODO(antonm): consider passing a receiver when constructing a cache. | |
| 11118 Handle<Object> receiver(isolate->global_context()->global(), isolate); | |
| 11119 | |
| 11120 Handle<Object> value; | |
| 11121 { | |
| 11122 // This handle is nor shared, nor used later, so it's safe. | |
| 11123 Object** argv[] = { key.location() }; | |
| 11124 bool pending_exception = false; | |
| 11125 value = Execution::Call(factory, | |
| 11126 receiver, | |
| 11127 1, | |
| 11128 argv, | |
| 11129 &pending_exception); | |
| 11130 if (pending_exception) return Failure::Exception(); | |
| 11131 } | |
| 11132 | |
| 11133 cache->set(index, *key); | |
| 11134 cache->set(index + 1, *value); | |
| 11135 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(index)); | |
| 11136 | |
| 11137 return *value; | |
| 11138 } | |
| 11139 | |
| 11140 | |
| 11141 static MaybeObject* Runtime_GetFromCache(RUNTIME_CALLING_CONVENTION) { | 11144 static MaybeObject* Runtime_GetFromCache(RUNTIME_CALLING_CONVENTION) { |
| 11142 RUNTIME_GET_ISOLATE; | 11145 RUNTIME_GET_ISOLATE; |
| 11143 // This is only called from codegen, so checks might be more lax. | 11146 // This is only called from codegen, so checks might be more lax. |
| 11144 CONVERT_CHECKED(FixedArray, cache, args[0]); | 11147 CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]); |
| 11145 Object* key = args[1]; | 11148 Object* key = args[1]; |
| 11146 | 11149 |
| 11147 const int finger_index = | 11150 int finger_index = cache->finger_index(); |
| 11148 Smi::cast(cache->get(JSFunctionResultCache::kFingerIndex))->value(); | |
| 11149 | |
| 11150 Object* o = cache->get(finger_index); | 11151 Object* o = cache->get(finger_index); |
| 11151 if (o == key) { | 11152 if (o == key) { |
| 11152 // The fastest case: hit the same place again. | 11153 // The fastest case: hit the same place again. |
| 11153 return cache->get(finger_index + 1); | 11154 return cache->get(finger_index + 1); |
| 11154 } | 11155 } |
| 11155 | 11156 |
| 11156 for (int i = finger_index - 2; | 11157 for (int i = finger_index - 2; |
| 11157 i >= JSFunctionResultCache::kEntriesIndex; | 11158 i >= JSFunctionResultCache::kEntriesIndex; |
| 11158 i -= 2) { | 11159 i -= 2) { |
| 11159 o = cache->get(i); | 11160 o = cache->get(i); |
| 11160 if (o == key) { | 11161 if (o == key) { |
| 11161 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i)); | 11162 cache->set_finger_index(i); |
| 11162 return cache->get(i + 1); | 11163 return cache->get(i + 1); |
| 11163 } | 11164 } |
| 11164 } | 11165 } |
| 11165 | 11166 |
| 11166 const int size = | 11167 int size = cache->size(); |
| 11167 Smi::cast(cache->get(JSFunctionResultCache::kCacheSizeIndex))->value(); | |
| 11168 ASSERT(size <= cache->length()); | 11168 ASSERT(size <= cache->length()); |
| 11169 | 11169 |
| 11170 for (int i = size - 2; i > finger_index; i -= 2) { | 11170 for (int i = size - 2; i > finger_index; i -= 2) { |
| 11171 o = cache->get(i); | 11171 o = cache->get(i); |
| 11172 if (o == key) { | 11172 if (o == key) { |
| 11173 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i)); | 11173 cache->set_finger_index(i); |
| 11174 return cache->get(i + 1); | 11174 return cache->get(i + 1); |
| 11175 } | 11175 } |
| 11176 } | 11176 } |
| 11177 | 11177 |
| 11178 // Cache miss. If we have spare room, put new data into it, otherwise | 11178 // There is no value in the cache. Invoke the function and cache result. |
| 11179 // evict post finger entry which must be least recently used. | 11179 HandleScope scope(isolate); |
| 11180 if (size < cache->length()) { | 11180 |
| 11181 cache->set(JSFunctionResultCache::kCacheSizeIndex, Smi::FromInt(size + 2)); | 11181 Handle<JSFunctionResultCache> cache_handle(cache); |
| 11182 return CacheMiss(isolate, cache, size, key); | 11182 Handle<Object> key_handle(key); |
| 11183 Handle<Object> value; |
| 11184 { |
| 11185 Handle<JSFunction> factory(JSFunction::cast( |
| 11186 cache_handle->get(JSFunctionResultCache::kFactoryIndex))); |
| 11187 // TODO(antonm): consider passing a receiver when constructing a cache. |
| 11188 Handle<Object> receiver(isolate->global_context()->global()); |
| 11189 // This handle is nor shared, nor used later, so it's safe. |
| 11190 Object** argv[] = { key_handle.location() }; |
| 11191 bool pending_exception = false; |
| 11192 value = Execution::Call(factory, |
| 11193 receiver, |
| 11194 1, |
| 11195 argv, |
| 11196 &pending_exception); |
| 11197 if (pending_exception) return Failure::Exception(); |
| 11198 } |
| 11199 |
| 11200 #ifdef DEBUG |
| 11201 cache_handle->JSFunctionResultCacheVerify(); |
| 11202 #endif |
| 11203 |
| 11204 // Function invocation may have cleared the cache. Reread all the data. |
| 11205 finger_index = cache_handle->finger_index(); |
| 11206 size = cache_handle->size(); |
| 11207 |
| 11208 // If we have spare room, put new data into it, otherwise evict post finger |
| 11209 // entry which is likely to be the least recently used. |
| 11210 int index = -1; |
| 11211 if (size < cache_handle->length()) { |
| 11212 cache_handle->set_size(size + JSFunctionResultCache::kEntrySize); |
| 11213 index = size; |
| 11183 } else { | 11214 } else { |
| 11184 int target_index = finger_index + JSFunctionResultCache::kEntrySize; | 11215 index = finger_index + JSFunctionResultCache::kEntrySize; |
| 11185 if (target_index == cache->length()) { | 11216 if (index == cache_handle->length()) { |
| 11186 target_index = JSFunctionResultCache::kEntriesIndex; | 11217 index = JSFunctionResultCache::kEntriesIndex; |
| 11187 } | 11218 } |
| 11188 return CacheMiss(isolate, cache, target_index, key); | |
| 11189 } | 11219 } |
| 11220 |
| 11221 ASSERT(index % 2 == 0); |
| 11222 ASSERT(index >= JSFunctionResultCache::kEntriesIndex); |
| 11223 ASSERT(index < cache_handle->length()); |
| 11224 |
| 11225 cache_handle->set(index, *key_handle); |
| 11226 cache_handle->set(index + 1, *value); |
| 11227 cache_handle->set_finger_index(index); |
| 11228 |
| 11229 #ifdef DEBUG |
| 11230 cache_handle->JSFunctionResultCacheVerify(); |
| 11231 #endif |
| 11232 |
| 11233 return *value; |
| 11190 } | 11234 } |
| 11191 | 11235 |
| 11192 #ifdef DEBUG | 11236 #ifdef DEBUG |
| 11193 // ListNatives is ONLY used by the fuzz-natives.js in debug mode | 11237 // ListNatives is ONLY used by the fuzz-natives.js in debug mode |
| 11194 // Exclude the code in release mode. | 11238 // Exclude the code in release mode. |
| 11195 static MaybeObject* Runtime_ListNatives(RUNTIME_CALLING_CONVENTION) { | 11239 static MaybeObject* Runtime_ListNatives(RUNTIME_CALLING_CONVENTION) { |
| 11196 RUNTIME_GET_ISOLATE; | 11240 RUNTIME_GET_ISOLATE; |
| 11197 ASSERT(args.length() == 0); | 11241 ASSERT(args.length() == 0); |
| 11198 HandleScope scope(isolate); | 11242 HandleScope scope(isolate); |
| 11199 Handle<JSArray> result = isolate->factory()->NewJSArray(0); | 11243 Handle<JSArray> result = isolate->factory()->NewJSArray(0); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11316 } else { | 11360 } else { |
| 11317 // Handle last resort GC and make sure to allow future allocations | 11361 // Handle last resort GC and make sure to allow future allocations |
| 11318 // to grow the heap without causing GCs (if possible). | 11362 // to grow the heap without causing GCs (if possible). |
| 11319 COUNTERS->gc_last_resort_from_js()->Increment(); | 11363 COUNTERS->gc_last_resort_from_js()->Increment(); |
| 11320 HEAP->CollectAllGarbage(false); | 11364 HEAP->CollectAllGarbage(false); |
| 11321 } | 11365 } |
| 11322 } | 11366 } |
| 11323 | 11367 |
| 11324 | 11368 |
| 11325 } } // namespace v8::internal | 11369 } } // namespace v8::internal |
| OLD | NEW |