| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 ScriptData* ScriptData::New(unsigned* data, int length) { | 1100 ScriptData* ScriptData::New(unsigned* data, int length) { |
| 1101 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length)); | 1101 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length)); |
| 1102 } | 1102 } |
| 1103 | 1103 |
| 1104 | 1104 |
| 1105 // --- S c r i p t --- | 1105 // --- S c r i p t --- |
| 1106 | 1106 |
| 1107 | 1107 |
| 1108 Local<Script> Script::New(v8::Handle<String> source, | 1108 Local<Script> Script::New(v8::Handle<String> source, |
| 1109 v8::ScriptOrigin* origin, | 1109 v8::ScriptOrigin* origin, |
| 1110 v8::ScriptData* script_data) { | 1110 v8::ScriptData* pre_data, |
| 1111 v8::Handle<String> script_data) { |
| 1111 ON_BAILOUT("v8::Script::New()", return Local<Script>()); | 1112 ON_BAILOUT("v8::Script::New()", return Local<Script>()); |
| 1112 LOG_API("Script::New"); | 1113 LOG_API("Script::New"); |
| 1113 ENTER_V8; | 1114 ENTER_V8; |
| 1114 i::Handle<i::String> str = Utils::OpenHandle(*source); | 1115 i::Handle<i::String> str = Utils::OpenHandle(*source); |
| 1115 i::Handle<i::Object> name_obj; | 1116 i::Handle<i::Object> name_obj; |
| 1116 int line_offset = 0; | 1117 int line_offset = 0; |
| 1117 int column_offset = 0; | 1118 int column_offset = 0; |
| 1118 if (origin != NULL) { | 1119 if (origin != NULL) { |
| 1119 if (!origin->ResourceName().IsEmpty()) { | 1120 if (!origin->ResourceName().IsEmpty()) { |
| 1120 name_obj = Utils::OpenHandle(*origin->ResourceName()); | 1121 name_obj = Utils::OpenHandle(*origin->ResourceName()); |
| 1121 } | 1122 } |
| 1122 if (!origin->ResourceLineOffset().IsEmpty()) { | 1123 if (!origin->ResourceLineOffset().IsEmpty()) { |
| 1123 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value()); | 1124 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value()); |
| 1124 } | 1125 } |
| 1125 if (!origin->ResourceColumnOffset().IsEmpty()) { | 1126 if (!origin->ResourceColumnOffset().IsEmpty()) { |
| 1126 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value()); | 1127 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value()); |
| 1127 } | 1128 } |
| 1128 } | 1129 } |
| 1129 EXCEPTION_PREAMBLE(); | 1130 EXCEPTION_PREAMBLE(); |
| 1130 i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data); | 1131 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data); |
| 1131 // We assert that the pre-data is sane, even though we can actually | 1132 // We assert that the pre-data is sane, even though we can actually |
| 1132 // handle it if it turns out not to be in release mode. | 1133 // handle it if it turns out not to be in release mode. |
| 1133 ASSERT(pre_data == NULL || pre_data->SanityCheck()); | 1134 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck()); |
| 1134 // If the pre-data isn't sane we simply ignore it | 1135 // If the pre-data isn't sane we simply ignore it |
| 1135 if (pre_data != NULL && !pre_data->SanityCheck()) { | 1136 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) { |
| 1136 pre_data = NULL; | 1137 pre_data_impl = NULL; |
| 1137 } | 1138 } |
| 1138 i::Handle<i::JSFunction> boilerplate = | 1139 i::Handle<i::JSFunction> boilerplate = |
| 1139 i::Compiler::Compile(str, | 1140 i::Compiler::Compile(str, |
| 1140 name_obj, | 1141 name_obj, |
| 1141 line_offset, | 1142 line_offset, |
| 1142 column_offset, | 1143 column_offset, |
| 1143 NULL, | 1144 NULL, |
| 1144 pre_data, | 1145 pre_data_impl, |
| 1146 Utils::OpenHandle(*script_data), |
| 1145 i::NOT_NATIVES_CODE); | 1147 i::NOT_NATIVES_CODE); |
| 1146 has_pending_exception = boilerplate.is_null(); | 1148 has_pending_exception = boilerplate.is_null(); |
| 1147 EXCEPTION_BAILOUT_CHECK(Local<Script>()); | 1149 EXCEPTION_BAILOUT_CHECK(Local<Script>()); |
| 1148 return Local<Script>(ToApi<Script>(boilerplate)); | 1150 return Local<Script>(ToApi<Script>(boilerplate)); |
| 1149 } | 1151 } |
| 1150 | 1152 |
| 1151 | 1153 |
| 1152 Local<Script> Script::New(v8::Handle<String> source, | 1154 Local<Script> Script::New(v8::Handle<String> source, |
| 1153 v8::Handle<Value> file_name) { | 1155 v8::Handle<Value> file_name) { |
| 1154 ScriptOrigin origin(file_name); | 1156 ScriptOrigin origin(file_name); |
| 1155 return New(source, &origin); | 1157 return New(source, &origin); |
| 1156 } | 1158 } |
| 1157 | 1159 |
| 1158 | 1160 |
| 1159 Local<Script> Script::Compile(v8::Handle<String> source, | 1161 Local<Script> Script::Compile(v8::Handle<String> source, |
| 1160 v8::ScriptOrigin* origin, | 1162 v8::ScriptOrigin* origin, |
| 1161 v8::ScriptData* script_data) { | 1163 v8::ScriptData* pre_data, |
| 1164 v8::Handle<String> script_data) { |
| 1162 ON_BAILOUT("v8::Script::Compile()", return Local<Script>()); | 1165 ON_BAILOUT("v8::Script::Compile()", return Local<Script>()); |
| 1163 LOG_API("Script::Compile"); | 1166 LOG_API("Script::Compile"); |
| 1164 ENTER_V8; | 1167 ENTER_V8; |
| 1165 Local<Script> generic = New(source, origin, script_data); | 1168 Local<Script> generic = New(source, origin, pre_data, script_data); |
| 1166 if (generic.IsEmpty()) | 1169 if (generic.IsEmpty()) |
| 1167 return generic; | 1170 return generic; |
| 1168 i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic); | 1171 i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic); |
| 1169 i::Handle<i::JSFunction> result = | 1172 i::Handle<i::JSFunction> result = |
| 1170 i::Factory::NewFunctionFromBoilerplate(boilerplate, | 1173 i::Factory::NewFunctionFromBoilerplate(boilerplate, |
| 1171 i::Top::global_context()); | 1174 i::Top::global_context()); |
| 1172 return Local<Script>(ToApi<Script>(result)); | 1175 return Local<Script>(ToApi<Script>(result)); |
| 1173 } | 1176 } |
| 1174 | 1177 |
| 1175 | 1178 |
| 1176 Local<Script> Script::Compile(v8::Handle<String> source, | 1179 Local<Script> Script::Compile(v8::Handle<String> source, |
| 1177 v8::Handle<Value> file_name) { | 1180 v8::Handle<Value> file_name, |
| 1181 v8::Handle<String> script_data) { |
| 1178 ScriptOrigin origin(file_name); | 1182 ScriptOrigin origin(file_name); |
| 1179 return Compile(source, &origin); | 1183 return Compile(source, &origin, 0, script_data); |
| 1180 } | 1184 } |
| 1181 | 1185 |
| 1182 | 1186 |
| 1183 Local<Value> Script::Run() { | 1187 Local<Value> Script::Run() { |
| 1184 ON_BAILOUT("v8::Script::Run()", return Local<Value>()); | 1188 ON_BAILOUT("v8::Script::Run()", return Local<Value>()); |
| 1185 LOG_API("Script::Run"); | 1189 LOG_API("Script::Run"); |
| 1186 ENTER_V8; | 1190 ENTER_V8; |
| 1187 i::Object* raw_result = NULL; | 1191 i::Object* raw_result = NULL; |
| 1188 { | 1192 { |
| 1189 HandleScope scope; | 1193 HandleScope scope; |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 | 2032 |
| 2029 Local<Value> v8::Object::GetPrototype() { | 2033 Local<Value> v8::Object::GetPrototype() { |
| 2030 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>()); | 2034 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>()); |
| 2031 ENTER_V8; | 2035 ENTER_V8; |
| 2032 i::Handle<i::Object> self = Utils::OpenHandle(this); | 2036 i::Handle<i::Object> self = Utils::OpenHandle(this); |
| 2033 i::Handle<i::Object> result = i::GetPrototype(self); | 2037 i::Handle<i::Object> result = i::GetPrototype(self); |
| 2034 return Utils::ToLocal(result); | 2038 return Utils::ToLocal(result); |
| 2035 } | 2039 } |
| 2036 | 2040 |
| 2037 | 2041 |
| 2042 bool v8::Object::SetPrototype(Handle<Value> value) { |
| 2043 ON_BAILOUT("v8::Object::SetPrototype()", return false); |
| 2044 ENTER_V8; |
| 2045 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 2046 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); |
| 2047 EXCEPTION_PREAMBLE(); |
| 2048 i::Handle<i::Object> result = i::SetPrototype(self, value_obj); |
| 2049 has_pending_exception = result.is_null(); |
| 2050 EXCEPTION_BAILOUT_CHECK(false); |
| 2051 return true; |
| 2052 } |
| 2053 |
| 2054 |
| 2038 Local<Object> v8::Object::FindInstanceInPrototypeChain( | 2055 Local<Object> v8::Object::FindInstanceInPrototypeChain( |
| 2039 v8::Handle<FunctionTemplate> tmpl) { | 2056 v8::Handle<FunctionTemplate> tmpl) { |
| 2040 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()", | 2057 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()", |
| 2041 return Local<v8::Object>()); | 2058 return Local<v8::Object>()); |
| 2042 ENTER_V8; | 2059 ENTER_V8; |
| 2043 i::JSObject* object = *Utils::OpenHandle(this); | 2060 i::JSObject* object = *Utils::OpenHandle(this); |
| 2044 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); | 2061 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); |
| 2045 while (!object->IsInstanceOf(tmpl_info)) { | 2062 while (!object->IsInstanceOf(tmpl_info)) { |
| 2046 i::Object* prototype = object->GetPrototype(); | 2063 i::Object* prototype = object->GetPrototype(); |
| 2047 if (!prototype->IsJSObject()) return Local<Object>(); | 2064 if (!prototype->IsJSObject()) return Local<Object>(); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2190 | 2207 |
| 2191 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( | 2208 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( |
| 2192 Handle<String> key) { | 2209 Handle<String> key) { |
| 2193 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()", | 2210 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()", |
| 2194 return Local<Value>()); | 2211 return Local<Value>()); |
| 2195 ENTER_V8; | 2212 ENTER_V8; |
| 2196 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); | 2213 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); |
| 2197 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); | 2214 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); |
| 2198 i::LookupResult lookup; | 2215 i::LookupResult lookup; |
| 2199 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); | 2216 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); |
| 2200 if (lookup.IsValid()) { | 2217 if (lookup.IsProperty()) { |
| 2201 PropertyAttributes attributes; | 2218 PropertyAttributes attributes; |
| 2202 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, | 2219 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, |
| 2203 &lookup, | 2220 &lookup, |
| 2204 *key_obj, | 2221 *key_obj, |
| 2205 &attributes)); | 2222 &attributes)); |
| 2206 return Utils::ToLocal(result); | 2223 return Utils::ToLocal(result); |
| 2207 } | 2224 } |
| 2208 return Local<Value>(); // No real property was found in prototype chain. | 2225 return Local<Value>(); // No real property was found in prototype chain. |
| 2209 } | 2226 } |
| 2210 | 2227 |
| 2211 | 2228 |
| 2212 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { | 2229 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { |
| 2213 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>()); | 2230 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>()); |
| 2214 ENTER_V8; | 2231 ENTER_V8; |
| 2215 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); | 2232 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); |
| 2216 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); | 2233 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); |
| 2217 i::LookupResult lookup; | 2234 i::LookupResult lookup; |
| 2218 self_obj->LookupRealNamedProperty(*key_obj, &lookup); | 2235 self_obj->LookupRealNamedProperty(*key_obj, &lookup); |
| 2219 if (lookup.IsValid()) { | 2236 if (lookup.IsProperty()) { |
| 2220 PropertyAttributes attributes; | 2237 PropertyAttributes attributes; |
| 2221 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, | 2238 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, |
| 2222 &lookup, | 2239 &lookup, |
| 2223 *key_obj, | 2240 *key_obj, |
| 2224 &attributes)); | 2241 &attributes)); |
| 2225 return Utils::ToLocal(result); | 2242 return Utils::ToLocal(result); |
| 2226 } | 2243 } |
| 2227 return Local<Value>(); // No real property was found in prototype chain. | 2244 return Local<Value>(); // No real property was found in prototype chain. |
| 2228 } | 2245 } |
| 2229 | 2246 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2441 func->shared()->set_name(*Utils::OpenHandle(*name)); | 2458 func->shared()->set_name(*Utils::OpenHandle(*name)); |
| 2442 } | 2459 } |
| 2443 | 2460 |
| 2444 | 2461 |
| 2445 Handle<Value> Function::GetName() const { | 2462 Handle<Value> Function::GetName() const { |
| 2446 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); | 2463 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); |
| 2447 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name())); | 2464 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name())); |
| 2448 } | 2465 } |
| 2449 | 2466 |
| 2450 | 2467 |
| 2468 ScriptOrigin Function::GetScriptOrigin() const { |
| 2469 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); |
| 2470 if (func->shared()->script()->IsScript()) { |
| 2471 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); |
| 2472 v8::ScriptOrigin origin( |
| 2473 Utils::ToLocal(i::Handle<i::Object>(script->name())), |
| 2474 v8::Integer::New(script->line_offset()->value()), |
| 2475 v8::Integer::New(script->column_offset()->value())); |
| 2476 return origin; |
| 2477 } |
| 2478 return v8::ScriptOrigin(Handle<Value>()); |
| 2479 } |
| 2480 |
| 2481 |
| 2482 const int Function::kLineOffsetNotFound = -1; |
| 2483 |
| 2484 |
| 2485 int Function::GetScriptLineNumber() const { |
| 2486 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); |
| 2487 if (func->shared()->script()->IsScript()) { |
| 2488 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); |
| 2489 return i::GetScriptLineNumber(script, func->shared()->start_position()); |
| 2490 } |
| 2491 return kLineOffsetNotFound; |
| 2492 } |
| 2493 |
| 2494 |
| 2495 namespace { |
| 2496 |
| 2497 // Tracks string usage to help make better decisions when |
| 2498 // externalizing strings. |
| 2499 // |
| 2500 // Implementation note: internally this class only tracks fresh |
| 2501 // strings and keeps a single use counter for them. |
| 2502 class StringTracker { |
| 2503 public: |
| 2504 // Records that the given string's characters were copied to some |
| 2505 // external buffer. If this happens often we should honor |
| 2506 // externalization requests for the string. |
| 2507 static void RecordWrite(i::Handle<i::String> string) { |
| 2508 i::Address address = reinterpret_cast<i::Address>(*string); |
| 2509 i::Address top = i::Heap::NewSpaceTop(); |
| 2510 if (IsFreshString(address, top)) { |
| 2511 IncrementUseCount(top); |
| 2512 } |
| 2513 } |
| 2514 |
| 2515 // Estimates freshness and use frequency of the given string based |
| 2516 // on how close it is to the new space top and the recorded usage |
| 2517 // history. |
| 2518 static inline bool IsFreshUnusedString(i::Handle<i::String> string) { |
| 2519 i::Address address = reinterpret_cast<i::Address>(*string); |
| 2520 i::Address top = i::Heap::NewSpaceTop(); |
| 2521 return IsFreshString(address, top) && IsUseCountLow(top); |
| 2522 } |
| 2523 |
| 2524 private: |
| 2525 static inline bool IsFreshString(i::Address string, i::Address top) { |
| 2526 return top - kFreshnessLimit <= string && string <= top; |
| 2527 } |
| 2528 |
| 2529 static inline bool IsUseCountLow(i::Address top) { |
| 2530 if (last_top_ != top) return true; |
| 2531 return use_count_ < kUseLimit; |
| 2532 } |
| 2533 |
| 2534 static inline void IncrementUseCount(i::Address top) { |
| 2535 if (last_top_ != top) { |
| 2536 use_count_ = 0; |
| 2537 last_top_ = top; |
| 2538 } |
| 2539 ++use_count_; |
| 2540 } |
| 2541 |
| 2542 // How close to the new space top a fresh string has to be. |
| 2543 static const int kFreshnessLimit = 1024; |
| 2544 |
| 2545 // The number of uses required to consider a string useful. |
| 2546 static const int kUseLimit = 32; |
| 2547 |
| 2548 // Single use counter shared by all fresh strings. |
| 2549 static int use_count_; |
| 2550 |
| 2551 // Last new space top when the use count above was valid. |
| 2552 static i::Address last_top_; |
| 2553 }; |
| 2554 |
| 2555 int StringTracker::use_count_ = 0; |
| 2556 i::Address StringTracker::last_top_ = NULL; |
| 2557 |
| 2558 } // namespace |
| 2559 |
| 2560 |
| 2451 int String::Length() const { | 2561 int String::Length() const { |
| 2452 if (IsDeadCheck("v8::String::Length()")) return 0; | 2562 if (IsDeadCheck("v8::String::Length()")) return 0; |
| 2453 return Utils::OpenHandle(this)->length(); | 2563 return Utils::OpenHandle(this)->length(); |
| 2454 } | 2564 } |
| 2455 | 2565 |
| 2456 | 2566 |
| 2457 int String::Utf8Length() const { | 2567 int String::Utf8Length() const { |
| 2458 if (IsDeadCheck("v8::String::Utf8Length()")) return 0; | 2568 if (IsDeadCheck("v8::String::Utf8Length()")) return 0; |
| 2459 return Utils::OpenHandle(this)->Utf8Length(); | 2569 return Utils::OpenHandle(this)->Utf8Length(); |
| 2460 } | 2570 } |
| 2461 | 2571 |
| 2462 | 2572 |
| 2463 int String::WriteUtf8(char* buffer, int capacity) const { | 2573 int String::WriteUtf8(char* buffer, int capacity) const { |
| 2464 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0; | 2574 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0; |
| 2465 LOG_API("String::WriteUtf8"); | 2575 LOG_API("String::WriteUtf8"); |
| 2466 ENTER_V8; | 2576 ENTER_V8; |
| 2467 i::Handle<i::String> str = Utils::OpenHandle(this); | 2577 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 2578 StringTracker::RecordWrite(str); |
| 2468 write_input_buffer.Reset(0, *str); | 2579 write_input_buffer.Reset(0, *str); |
| 2469 int len = str->length(); | 2580 int len = str->length(); |
| 2470 // Encode the first K - 3 bytes directly into the buffer since we | 2581 // Encode the first K - 3 bytes directly into the buffer since we |
| 2471 // know there's room for them. If no capacity is given we copy all | 2582 // know there's room for them. If no capacity is given we copy all |
| 2472 // of them here. | 2583 // of them here. |
| 2473 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); | 2584 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); |
| 2474 int i; | 2585 int i; |
| 2475 int pos = 0; | 2586 int pos = 0; |
| 2476 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) { | 2587 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) { |
| 2477 i::uc32 c = write_input_buffer.GetNext(); | 2588 i::uc32 c = write_input_buffer.GetNext(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2501 return pos; | 2612 return pos; |
| 2502 } | 2613 } |
| 2503 | 2614 |
| 2504 | 2615 |
| 2505 int String::WriteAscii(char* buffer, int start, int length) const { | 2616 int String::WriteAscii(char* buffer, int start, int length) const { |
| 2506 if (IsDeadCheck("v8::String::WriteAscii()")) return 0; | 2617 if (IsDeadCheck("v8::String::WriteAscii()")) return 0; |
| 2507 LOG_API("String::WriteAscii"); | 2618 LOG_API("String::WriteAscii"); |
| 2508 ENTER_V8; | 2619 ENTER_V8; |
| 2509 ASSERT(start >= 0 && length >= -1); | 2620 ASSERT(start >= 0 && length >= -1); |
| 2510 i::Handle<i::String> str = Utils::OpenHandle(this); | 2621 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 2622 StringTracker::RecordWrite(str); |
| 2511 // Flatten the string for efficiency. This applies whether we are | 2623 // Flatten the string for efficiency. This applies whether we are |
| 2512 // using StringInputBuffer or Get(i) to access the characters. | 2624 // using StringInputBuffer or Get(i) to access the characters. |
| 2513 str->TryFlattenIfNotFlat(); | 2625 str->TryFlattenIfNotFlat(); |
| 2514 int end = length; | 2626 int end = length; |
| 2515 if ( (length == -1) || (length > str->length() - start) ) | 2627 if ( (length == -1) || (length > str->length() - start) ) |
| 2516 end = str->length() - start; | 2628 end = str->length() - start; |
| 2517 if (end < 0) return 0; | 2629 if (end < 0) return 0; |
| 2518 write_input_buffer.Reset(start, *str); | 2630 write_input_buffer.Reset(start, *str); |
| 2519 int i; | 2631 int i; |
| 2520 for (i = 0; i < end; i++) { | 2632 for (i = 0; i < end; i++) { |
| 2521 char c = static_cast<char>(write_input_buffer.GetNext()); | 2633 char c = static_cast<char>(write_input_buffer.GetNext()); |
| 2522 if (c == '\0') c = ' '; | 2634 if (c == '\0') c = ' '; |
| 2523 buffer[i] = c; | 2635 buffer[i] = c; |
| 2524 } | 2636 } |
| 2525 if (length == -1 || i < length) | 2637 if (length == -1 || i < length) |
| 2526 buffer[i] = '\0'; | 2638 buffer[i] = '\0'; |
| 2527 return i; | 2639 return i; |
| 2528 } | 2640 } |
| 2529 | 2641 |
| 2530 | 2642 |
| 2531 int String::Write(uint16_t* buffer, int start, int length) const { | 2643 int String::Write(uint16_t* buffer, int start, int length) const { |
| 2532 if (IsDeadCheck("v8::String::Write()")) return 0; | 2644 if (IsDeadCheck("v8::String::Write()")) return 0; |
| 2533 LOG_API("String::Write"); | 2645 LOG_API("String::Write"); |
| 2534 ENTER_V8; | 2646 ENTER_V8; |
| 2535 ASSERT(start >= 0 && length >= -1); | 2647 ASSERT(start >= 0 && length >= -1); |
| 2536 i::Handle<i::String> str = Utils::OpenHandle(this); | 2648 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 2649 StringTracker::RecordWrite(str); |
| 2537 int end = length; | 2650 int end = length; |
| 2538 if ( (length == -1) || (length > str->length() - start) ) | 2651 if ( (length == -1) || (length > str->length() - start) ) |
| 2539 end = str->length() - start; | 2652 end = str->length() - start; |
| 2540 if (end < 0) return 0; | 2653 if (end < 0) return 0; |
| 2541 i::String::WriteToFlat(*str, buffer, start, end); | 2654 i::String::WriteToFlat(*str, buffer, start, end); |
| 2542 if (length == -1 || end < length) | 2655 if (length == -1 || end < length) |
| 2543 buffer[end] = '\0'; | 2656 buffer[end] = '\0'; |
| 2544 return end; | 2657 return end; |
| 2545 } | 2658 } |
| 2546 | 2659 |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3095 i::ExternalStringTable::AddString(*result); | 3208 i::ExternalStringTable::AddString(*result); |
| 3096 return Utils::ToLocal(result); | 3209 return Utils::ToLocal(result); |
| 3097 } | 3210 } |
| 3098 | 3211 |
| 3099 | 3212 |
| 3100 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { | 3213 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 3101 if (IsDeadCheck("v8::String::MakeExternal()")) return false; | 3214 if (IsDeadCheck("v8::String::MakeExternal()")) return false; |
| 3102 if (this->IsExternal()) return false; // Already an external string. | 3215 if (this->IsExternal()) return false; // Already an external string. |
| 3103 ENTER_V8; | 3216 ENTER_V8; |
| 3104 i::Handle<i::String> obj = Utils::OpenHandle(this); | 3217 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 3218 if (StringTracker::IsFreshUnusedString(obj)) return false; |
| 3105 bool result = obj->MakeExternal(resource); | 3219 bool result = obj->MakeExternal(resource); |
| 3106 if (result && !obj->IsSymbol()) { | 3220 if (result && !obj->IsSymbol()) { |
| 3107 i::ExternalStringTable::AddString(*obj); | 3221 i::ExternalStringTable::AddString(*obj); |
| 3108 } | 3222 } |
| 3109 return result; | 3223 return result; |
| 3110 } | 3224 } |
| 3111 | 3225 |
| 3112 | 3226 |
| 3113 Local<String> v8::String::NewExternal( | 3227 Local<String> v8::String::NewExternal( |
| 3114 v8::String::ExternalAsciiStringResource* resource) { | 3228 v8::String::ExternalAsciiStringResource* resource) { |
| 3115 EnsureInitialized("v8::String::NewExternal()"); | 3229 EnsureInitialized("v8::String::NewExternal()"); |
| 3116 LOG_API("String::NewExternal"); | 3230 LOG_API("String::NewExternal"); |
| 3117 ENTER_V8; | 3231 ENTER_V8; |
| 3118 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource); | 3232 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource); |
| 3119 i::ExternalStringTable::AddString(*result); | 3233 i::ExternalStringTable::AddString(*result); |
| 3120 return Utils::ToLocal(result); | 3234 return Utils::ToLocal(result); |
| 3121 } | 3235 } |
| 3122 | 3236 |
| 3123 | 3237 |
| 3124 bool v8::String::MakeExternal( | 3238 bool v8::String::MakeExternal( |
| 3125 v8::String::ExternalAsciiStringResource* resource) { | 3239 v8::String::ExternalAsciiStringResource* resource) { |
| 3126 if (IsDeadCheck("v8::String::MakeExternal()")) return false; | 3240 if (IsDeadCheck("v8::String::MakeExternal()")) return false; |
| 3127 if (this->IsExternal()) return false; // Already an external string. | 3241 if (this->IsExternal()) return false; // Already an external string. |
| 3128 ENTER_V8; | 3242 ENTER_V8; |
| 3129 i::Handle<i::String> obj = Utils::OpenHandle(this); | 3243 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 3244 if (StringTracker::IsFreshUnusedString(obj)) return false; |
| 3130 bool result = obj->MakeExternal(resource); | 3245 bool result = obj->MakeExternal(resource); |
| 3131 if (result && !obj->IsSymbol()) { | 3246 if (result && !obj->IsSymbol()) { |
| 3132 i::ExternalStringTable::AddString(*obj); | 3247 i::ExternalStringTable::AddString(*obj); |
| 3133 } | 3248 } |
| 3134 return result; | 3249 return result; |
| 3135 } | 3250 } |
| 3136 | 3251 |
| 3137 | 3252 |
| 3138 bool v8::String::CanMakeExternal() { | 3253 bool v8::String::CanMakeExternal() { |
| 3139 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false; | 3254 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false; |
| 3140 i::Handle<i::String> obj = Utils::OpenHandle(this); | 3255 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 3256 if (StringTracker::IsFreshUnusedString(obj)) return false; |
| 3141 int size = obj->Size(); // Byte size of the original string. | 3257 int size = obj->Size(); // Byte size of the original string. |
| 3142 if (size < i::ExternalString::kSize) | 3258 if (size < i::ExternalString::kSize) |
| 3143 return false; | 3259 return false; |
| 3144 i::StringShape shape(*obj); | 3260 i::StringShape shape(*obj); |
| 3145 return !shape.IsExternal(); | 3261 return !shape.IsExternal(); |
| 3146 } | 3262 } |
| 3147 | 3263 |
| 3148 | 3264 |
| 3149 Local<v8::Object> v8::Object::New() { | 3265 Local<v8::Object> v8::Object::New() { |
| 3150 EnsureInitialized("v8::Object::New()"); | 3266 EnsureInitialized("v8::Object::New()"); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3354 | 3470 |
| 3355 | 3471 |
| 3356 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { | 3472 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { |
| 3357 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return; | 3473 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return; |
| 3358 i::Heap::SetGlobalGCEpilogueCallback(callback); | 3474 i::Heap::SetGlobalGCEpilogueCallback(callback); |
| 3359 } | 3475 } |
| 3360 | 3476 |
| 3361 | 3477 |
| 3362 void V8::PauseProfiler() { | 3478 void V8::PauseProfiler() { |
| 3363 #ifdef ENABLE_LOGGING_AND_PROFILING | 3479 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3364 i::Logger::PauseProfiler(PROFILER_MODULE_CPU); | 3480 PauseProfilerEx(PROFILER_MODULE_CPU); |
| 3365 #endif | 3481 #endif |
| 3366 } | 3482 } |
| 3367 | 3483 |
| 3368 | 3484 |
| 3369 void V8::ResumeProfiler() { | 3485 void V8::ResumeProfiler() { |
| 3370 #ifdef ENABLE_LOGGING_AND_PROFILING | 3486 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3371 i::Logger::ResumeProfiler(PROFILER_MODULE_CPU); | 3487 ResumeProfilerEx(PROFILER_MODULE_CPU); |
| 3372 #endif | 3488 #endif |
| 3373 } | 3489 } |
| 3374 | 3490 |
| 3375 | 3491 |
| 3376 bool V8::IsProfilerPaused() { | 3492 bool V8::IsProfilerPaused() { |
| 3377 #ifdef ENABLE_LOGGING_AND_PROFILING | 3493 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3378 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU; | 3494 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU; |
| 3379 #else | 3495 #else |
| 3380 return true; | 3496 return true; |
| 3381 #endif | 3497 #endif |
| 3382 } | 3498 } |
| 3383 | 3499 |
| 3384 | 3500 |
| 3385 void V8::ResumeProfilerEx(int flags) { | 3501 void V8::ResumeProfilerEx(int flags, int tag) { |
| 3386 #ifdef ENABLE_LOGGING_AND_PROFILING | 3502 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3387 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) { | 3503 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) { |
| 3388 // Snapshot mode: resume modules, perform GC, then pause only | 3504 // Snapshot mode: resume modules, perform GC, then pause only |
| 3389 // those modules which haven't been started prior to making a | 3505 // those modules which haven't been started prior to making a |
| 3390 // snapshot. | 3506 // snapshot. |
| 3391 | 3507 |
| 3392 // Reset snapshot flag and CPU module flags. | 3508 // Reset snapshot flag and CPU module flags. |
| 3393 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU); | 3509 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU); |
| 3394 const int current_flags = i::Logger::GetActiveProfilerModules(); | 3510 const int current_flags = i::Logger::GetActiveProfilerModules(); |
| 3395 i::Logger::ResumeProfiler(flags); | 3511 i::Logger::ResumeProfiler(flags, tag); |
| 3396 i::Heap::CollectAllGarbage(false); | 3512 i::Heap::CollectAllGarbage(false); |
| 3397 i::Logger::PauseProfiler(~current_flags & flags); | 3513 i::Logger::PauseProfiler(~current_flags & flags, tag); |
| 3398 } else { | 3514 } else { |
| 3399 i::Logger::ResumeProfiler(flags); | 3515 i::Logger::ResumeProfiler(flags, tag); |
| 3400 } | 3516 } |
| 3401 #endif | 3517 #endif |
| 3402 } | 3518 } |
| 3403 | 3519 |
| 3404 | 3520 |
| 3405 void V8::PauseProfilerEx(int flags) { | 3521 void V8::PauseProfilerEx(int flags, int tag) { |
| 3406 #ifdef ENABLE_LOGGING_AND_PROFILING | 3522 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3407 i::Logger::PauseProfiler(flags); | 3523 i::Logger::PauseProfiler(flags, tag); |
| 3408 #endif | 3524 #endif |
| 3409 } | 3525 } |
| 3410 | 3526 |
| 3411 | 3527 |
| 3412 int V8::GetActiveProfilerModules() { | 3528 int V8::GetActiveProfilerModules() { |
| 3413 #ifdef ENABLE_LOGGING_AND_PROFILING | 3529 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3414 return i::Logger::GetActiveProfilerModules(); | 3530 return i::Logger::GetActiveProfilerModules(); |
| 3415 #else | 3531 #else |
| 3416 return PROFILER_MODULE_NONE; | 3532 return PROFILER_MODULE_NONE; |
| 3417 #endif | 3533 #endif |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3830 | 3946 |
| 3831 | 3947 |
| 3832 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { | 3948 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { |
| 3833 HandleScopeImplementer* thread_local = | 3949 HandleScopeImplementer* thread_local = |
| 3834 reinterpret_cast<HandleScopeImplementer*>(storage); | 3950 reinterpret_cast<HandleScopeImplementer*>(storage); |
| 3835 thread_local->IterateThis(v); | 3951 thread_local->IterateThis(v); |
| 3836 return storage + ArchiveSpacePerThread(); | 3952 return storage + ArchiveSpacePerThread(); |
| 3837 } | 3953 } |
| 3838 | 3954 |
| 3839 } } // namespace v8::internal | 3955 } } // namespace v8::internal |
| OLD | NEW |