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

Side by Side Diff: src/runtime.cc

Issue 6597029: [Isolates] Merge r 6300:6500 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/runtime.h ('k') | src/runtime-profiler.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 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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698